天天看點

02-SpringMVC_獲得使用者請求

問題:使用者的請求,是如何被背景獲得的,即使用者的請求資訊是怎麼配置設定給不同的處理器? 背景又是如何獲得使用者資料的?這些問題會後面的課程中一一解答

一、 使用@RequestMapping映射請求

  • SpringMVC使用@RequestMapping注解,為控制器指定可以處理哪些URL請求
  • DispathcherSevle截獲請求後,就通過控制器上@RequestMapping提供的映射資訊确定請求所對應的處理方法
  • 檢視@RequestMapping源碼,可以知道它可以修飾方法,也可以修飾類
02-SpringMVC_獲得使用者請求

1、@RequestMapping修飾方法

  • 測試類
  1. @Controller

  2. public class SpringMVCTest {

  3. @RequestMapping("/testMappingMethod")

  4. public String testRequestMapping(){

  5. System.out.println("testMappingMethod");

  6. return "success";

  7. }

  8. }

  • URL
  1. <a href="testMappingMethod"></a>

2 @RequestMapping修飾類

  •  測試類
  1. @RequestMapping("/mappingClass")

  2. @Controller

  3. public class MappingClassTest {

  4. @RequestMapping("/testMappingMethod")

  5. public String testRequestMapping(){

  6. System.out.println("testRequestMapping");

  7. return "success";

  8. }

  9. }

  • 請求的url
  1. <a href="mappingClass/testMappingMethod">testMappingClass</a>

3 總結

  • @RequestMapping可以标注在控制器類的定義或方法定義處。
    • 類定義:提供初步的請求映射資訊,相對于WEB應用的根目錄
    • 方法處:提供進一步細分映射資訊,相對于類定義處的URL;若類定義處未标注@RequestMapping,則方法處标注的URL相對WEB應用的根目錄

二、映射請求參數、請求方式或請求頭

  • @RequestMapping除了可以使用請求Url映射請求以外,還可以使用請求方法、請求參數及請求頭映射請求.對應的@RequestMapping源碼如下
  1. @Target({ElementType.METHOD, ElementType.TYPE})

  2. @Retention(RetentionPolicy.RUNTIME)

  3. @Documented

  4. @Mapping

  5. public @interface RequestMapping {

  6. ...

  7. RequestMethod[] method() default {};

  8. ...

  9. String[] params() default {};

  10. String[] headers() default {};

  11. ...

  12. }

  • @RequestMapping的vaule、method、params及headers分别表請求URL、請求方法、請求參數及請求頭的映射條件,他們之間是 “與” 的關系,聯合使用多個條件可讓請求映射更加精确化

1、method的屬性

  • 控制器
  1. @RequestMapping(value="/testMethod",method=RequestMethod.POST)

  2. public String testMethod(){

  3. System.out.println("testMethod");

  4. return "success";

  5. }

  • 超連結是使用get請求,是以不會成功
  1. <a href="mappingOther/testMethod">測試請求方式</a>

  • form請求
  1. <form action="mappingOther/testMethod" method="post">

  2. <input type="submit" value="送出">

  3. </form>

2、params的屬性 

2.1 params支援簡單的表達式

  • param1:表示請求必須包含名為param1的請求參數
  • !param1:表示請求不能包含名為param1的請求參數
  • param1!=value1:表示請求包含名為param1的參數,但其值不能為value1
  • {"param1=value1",param2}:請求必須包含名為param1和param2的兩個請求參數,且param1的參數的值必須是value1

2.2 測試

  • 控制器
  1. @RequestMapping(value="/testParams",params={"username","age!=10"})

  2. public String testParams(){

  3. System.out.println("testParams");

  4. return "success";

  5. }

含義:必須包含參數username和age,且age的值不能為10

  • 請求
  1. <a href="mappingOther/testParams?username=imentor&age=10">測試參數</a>

    不能成功,因為age的值為10

3、header

  • 獲得headers的值,可以通過firebug來檢視
02-SpringMVC_獲得使用者請求
  • 控制器中的編寫如下
  1. @RequestMapping(value="/testHeaders",headers={"zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3"})

  2. public String testHeaders(){

  3. System.out.println("testHeader");

  4. return "success";

  5. }

三、映射請求路徑

  • @RequestMapping支援Ant風格的請求路徑,見源碼
02-SpringMVC_獲得使用者請求

1、 Ant風格資源位址支援3種比對符

  • ?:比對檔案名中的一個字元
  • *  :比對檔案名中的任意字元
  • ** :比對多層路徑

2 @RequestMapping支援Ant風格的URL

  • /usercreateUser   :比對/user/createUser
  •                                     比對/user/aaa/bbb/createUser
  • /user/createUser??   :比對/user/createUseraa
  •                                      比對/user/createUserbb

3、測試

  • 控制器
  1. @RequestMapping(value="/user/*/createUser")

  2. public String createUser(){

  3. System.out.println("createUser");

  4. return "success";

  5. }

  • 請求
  1. a href="mappingOther/user/aaa/createUser">ant風格</a>

四、REST

1、知識點

  •  浏覽器form表單隻支援GET與POST請求,而DELETE、PUT等method并不支援,spring3.0添加了一個過濾器,可以将這些請求轉換為标準的http方法,使得支援GET、POST、PUT與DELETE請求,該過濾器為HiddenHttpMethodFilter。
  •  HiddenHttpMethodFilter的父類是OncePerRequestFilter,它繼承了父類的doFilterInternal方法,工作原理是将jsp頁面的form表單的method屬性值在doFilterInternal方法中轉化為标準的Http方法,即GET,、POST、 HEAD、OPTIONS、PUT、DELETE、TRACE,然後到Controller中找到對應的方法。例如,在使用注解時我們可能會在Controller中用于@RequestMapping(value = "list", method = RequestMethod.PUT),是以如果你的表單中使用的是<form method="put">,那麼這個表單會被送出到标了Method="PUT"的方法中。
  • REST:Representational State Transfer.即(資源)表現層狀态轉化。
    • 資源(Resources):網絡上的一個實體,它可以是一段文本、一張圖檔、一首歌曲、一種服務等。可以用一個URI指向它。第一種資源對應一個特定的URI.也就是說,URI即為每個資源的獨一無二的識别符。
    • 表現層(Representation):把資源具體呈現出來的形式,叫做它的表現層。比如,文本可以用txt格式表現,也可以用HTML格式、XML格式、JSON格式表現,甚至可以采用二進制格式。
    • 狀态轉化(State Transfer):每發出一個請求,就代表了用戶端和伺服器一次互動過程。HTTP協定,是一個無狀态協定,即所有的狀态都儲存在服務端。是以,如果客戶想要操作伺服器,必須通過某種手段,讓服務端發生“狀态轉化”。而這種轉化是建立在表現之上的。具體來說,就是HTTP協定裡面,四個表示操作方式的動詞
      • GET:擷取資源
      • POST:建立資源
      • PUT:更新資源
      • DELETE:删除資源
  • 示例
    • /order/1    HTTP GET:得到id=1的order
    • /order/1    HTTP DELETE:删除id=1的order
    • /order/1    HTTP PUT:更新id=1的order
    • /order/1    HTTP POST:新增id=1的order
  • HiddenHttpMethodFilter
    • 浏覽器form表單隻支援GET與POST請求,而DELETE、PUT等method并不支援
    • Spring3.0添加一個過濾器,可以将這些請求轉換為标準的http方法,使其支援GET、POST、PUT與DELETE請求

2、測試

  • 在web.xml檔案中HiddenHttpMethodFilter
  1. <filter>

  2. <filter-name>hiddenHttpMethodFilter</filter-name>

  3. <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>

  4. </filter>

  5. <filter-mapping>

  6. <filter-name>hiddenHttpMethodFilter</filter-name>

  7. <url-pattern>/*</url-pattern>

  8. </filter-mapping>

  • 控制器
  1. @RequestMapping("/testREST")

  2. @Controller

  3. public class TestREST {

  4. @RequestMapping(value="/testRest/{id}",method=RequestMethod.GET)

  5. public String testRestGet(@PathVariable Integer id){

  6. System.out.println("testRest GET:"+id);

  7. return "success";

  8. }

  9. @RequestMapping(value="/testRest/{id}",method=RequestMethod.POST)

  10. public String testRestPost(@PathVariable Integer id){

  11. System.out.println("testRest POST:"+id);

  12. return "success";

  13. }

  14. @RequestMapping(value="/testRest/{id}",method=RequestMethod.DELETE)

  15. public String testRestDelete(@PathVariable Integer id){

  16. System.out.println("testRest Delete:"+id);

  17. return "success";

  18. }

  19. @RequestMapping(value="/testRest/{id}",method=RequestMethod.PUT)

  20. public String testRestPut(@PathVariable Integer id){

  21. System.out.println("testRest Put:"+id);

  22. return "success";

  23. }

  24. }

  • 請求
  1. <a href="testREST/testRest/1">測試Get</a>

  2. <form action="testREST/testRest/1" method="post">

  3. <input type="submit" value="測試post">

  4. </form>

  5. <form action="testREST/testRest/1" method="post">

  6. <input type="hidden" name="_method" value="DELETE">

  7. <input type="submit" value="測試DELETE">

  8. </form>

  9. <form action="testREST/testRest/1" method="post">

  10. <input type="hidden" name="_method" value="PUT">

  11. <input type="submit" value="測試PUT">

  12. </form>

3、注意

  1. 如果用tomcat8作為伺服器,在測試DELETE和Put的時候,會報405錯誤
02-SpringMVC_獲得使用者請求

解決方法有三種

  • 一是将Tomcat8改為Tomcat7,在Tomcat7下運作是正常的.或者更新到tomcat 8.0.9以上版本
  • 二是将請求轉發(forward)改為redirect
  • 三是自己手動寫一個Filter來包裝HttpRequest中的getMethod方法

下面主要介紹一下第三種方法:也就是自己寫一個Filter來包裝從伺服器發回來的HttpRequest請求:

02-SpringMVC_獲得使用者請求

大緻說一下流程,   1. 在第1步中,用戶端發送請求至伺服器,這時如果發送的是POST請求且帶有以_method為名的參數會被Spring的HiddenHttpMethodFilter給攔截。   2. HiddenHttpMethodFilter内有一個靜态内部類通過繼承HttpServletRequestWrapper類并重寫getMethod()方法,将該方法傳回值設為_method隐藏域的值。   3. HiddenHttpMethodFilter在包裝好Request後,将請求發往伺服器的控制器中對應的方法處理器,這時的請求變成了圖中的 3、WrapperRequest by SpringFilter   4. 伺服器處理完請求後,産生了一個forward請求,産生相應的請求處理資訊發往用戶端,注意這時的request的getMethod()方法仍然是HiddenHttpMethodFilter包裝過的   5. 我們需要在伺服器的響應請求到達用戶端前進行攔截,這也是最關鍵的一步,通過自定義過濾器 MyMethodConvertingFilter  進一步包裝請求,将getMethod()方法傳回值改成POST或GET即可  

  1. public class MyMethodConvertingFilter implements Filter {

  2. @Override

  3. public void destroy() {

  4. // TODO Auto-generated method stub

  5. }

  6. @Override

  7. public void doFilter(ServletRequest request, ServletResponse response,

  8. FilterChain chain) throws IOException, ServletException {

  1. chain.doFilter(

    wrapRequest((HttpServletRequest) request), response);
  1. }

  2. @Override

  3. public void init(FilterConfig arg0) throws ServletException {

  4. // TODO Auto-generated method stub

  5. }

  6. private static HttpServletRequestWrapper wrapRequest(HttpServletRequest request) {

  7. return new HttpServletRequestWrapper(request) {

  8. @Override

  9. public String getMethod() {

  10. return "GET";

  11. }

  12. };

  13. }

  14. }

6. 在web.xml中配置該filter,注意dispatcher結點值必須為FORWARD。

  1. <filter-mapping>

  2. <filter-name>myFilter</filter-name>

  3. <url-pattern>/*</url-pattern>

  4. <dispatcher>FORWARD</dispatcher>

  5. </filter-mapping>

關注我們

師享空間的宗旨是分享知識,傳播價值。關注我們,及時獲得更多資訊。

02-SpringMVC_獲得使用者請求

捐贈我們

    如果您對我們的成果表示認同并且覺得對你有所幫助,歡迎您對我們捐贈^_^。         

02-SpringMVC_獲得使用者請求

轉載于:https://www.cnblogs.com/imentors/p/5009186.html