1. 程式人生 > >springMVC對映規則詳解

springMVC對映規則詳解

6.5、請求對映

處理器定義好了,那接下來我們應該定義功能處理方法,接收使用者請求處理並選擇檢視進行渲染。首先我們看一下圖6-1:

http請求資訊包含六部分資訊:
①請求方法,如GET或POST,表示提交的方式;
URL,請求的地址資訊;
③協議及版本
④請求頭資訊(包括Cookie資訊);
⑤回車換行(CRLF);
⑥請求內容區(即請求的內容或資料),如表單提交時的引數資料、URL請求引數(?abc=123 ?後邊的)等。
那此處我們可以看到有①、②、④、⑥一般是可變的,因此我們可以這些資訊進行請求到處理器的功能處理方法的對映,因此請求的對映分為如下幾種:

URL路徑對映:使用URL對映請求到處理器的功能處理方法;

請求方法對映限定:如限定功能處理方法只處理GET請求;

請求引數對映限定:如限定只處理包含“abc”請求引數的請求;

請求頭對映限定:如限定只處理“Accept=application/json”的請求。

接下來看看具體如何對映吧。

6.5.1、URL路徑對映

6.5.1.1、普通URL路徑對映

@RequestMapping(value={"/test1", "/user/create"}):多個URL路徑可以對映到同一個處理器的功能處理方法。

6.5.1.2、URI模板模式對映

@RequestMapping(value="/users/{userId}"):{×××}佔位符, 請求的URL可以是 “/users/123456”或

“/users/abcd”,通過6.6.5講的通過@PathVariable可以提取URI模板模式中的{×××}中的×××變數。

@RequestMapping(value="/users/{userId}/create"):這樣也是可以的,請求的URL可以是“/users/123/create”。

@RequestMapping(value="/users/{userId}/topics/{topicId}"):這樣也是可以的,請求的URL可以是“/users/123/topics/123”。

6.5.1.3、Ant風格的URL路徑對映

@RequestMapping(value="/users/**"):可以匹配“/users/abc/abc”,但“/users/123”將會被【URI模板模式對映中的“/users/{userId}”模式優先對映到】【詳見4.14的最長匹配優先

】。

@RequestMapping(value="/product?"):可匹配“/product1”或“/producta”,但不匹配“/product”或“/productaa”;

@RequestMapping(value="/product*"):可匹配“/productabc”或“/product”,但不匹配“/productabc/abc”;

@RequestMapping(value="/product/*"):可匹配“/product/abc”,但不匹配“/productabc”;

@RequestMapping(value="/products/**/{productId}"):可匹配“/products/abc/abc/123”或“/products/123”,也就是Ant風格和URI模板變數風格可混用;

此處需要注意的是【4.14中提到的最長匹配優先】,Ant風格的模式請參考4.14。

6.5.1.4、正則表示式風格的URL路徑對映

從Spring3.0開始支援正則表示式風格的URL路徑對映,格式為{變數名:正則表示式},這樣我們就可以通過6.6.5講的通過@PathVariable提取模式中的{×××:正則表示式匹配的值}中的×××變量了。

@RequestMapping(value="/products/{categoryCode:\\d+}-{pageNumber:\\d+}"):可以匹配“/products/123-1”,但不能匹配“/products/abc-1”,這樣可以設計更加嚴格的規則。

正則表示式風格的URL路徑對映是一種特殊的URI模板模式對映:

URI模板模式對映是{userId},不能指定模板變數的資料型別,如是數字還是字串;

正則表示式風格的URL路徑對映,可以指定模板變數的資料型別,可以將規則寫的相當複雜。

6.5.1.5、組合使用是“或”的關係

@RequestMapping(value={"/test1", "/user/create"}) 組合使用是或的關係,即“/test1”或“/user/create”請求URL路徑都可以對映到@RequestMapping指定的功能處理方法。

以上URL對映的測試類為:cn.javass.chapter6.web.controller.mapping.MappingController.Java

到此,我們學習了springWeb MVC提供的強大的URL路徑對映,而且可以實現非常複雜的URL規則。Spring Web MVC不僅僅提供URL路徑對映,還提供了其他強大的對映規則。接下來我們看一下請求方法對映限定吧。

6.5.2、請求方法對映限定

一般我們熟悉的表單一般分為兩步:第一步展示,第二步提交,如4.9、SimpleFormController那樣,那如何通過@RequestMapping來實現呢?

6.5.2.1、請求方法對映限定

我們熟知的,展示表單一般為GET請求方法;提交表單一般為POST請求方法。但6.5.1節講的URL路徑對映方式對任意請求方法是全盤接受的,因此我們需要某種方式來告訴相應的功能處理方法只處理如GET請求方法的請求或POST請求方法的請求。

接下來我們使用@RequestMapping來實現SimpleFormController的功能吧。

Java程式碼  收藏程式碼
  1. package cn.javass.chapter6.web.controller.method;  
  2. //省略import  
  3. @Controller  
  4. @RequestMapping("/customers/**")                                     //①處理器的通用對映字首  
  5. public class RequestMethodController {  
  6.     @RequestMapping(value="/create", method = RequestMethod.GET)//②類級別的@RequestMapping窄化  
  7.     public String showForm() {  
  8.         System.out.println("===============GET");  
  9.         return "customer/create";    
  10.     }  
  11.     @RequestMapping(value="/create", method = RequestMethod.POST)//③類級別的@RequestMapping窄化  
  12.     public String submit() {  
  13.         System.out.println("================POST");  
  14.         return "redirect:/success";          
  15.     }  
  16. }  

 處理器的通用對映字首(父路徑):表示該處理器只處理匹配“/customers/**”的請求;

對類級別的@RequestMapping進行窄化,表示showForm可處理匹配“/customers/**/create”且請求方法為“GET”的請求;

對類級別的@RequestMapping進行窄化,表示submit可處理匹配“/customers/**/create”且請求方法為“POST”的請求。

6.5.2.2、組合使用是“或”的關係

@RequestMapping(value="/methodOr",method = {RequestMethod.POST, RequestMethod.GET}):即請求方法可以是 GET 或 POST。

提示:

1、一般瀏覽器只支援GET、POST請求方法,如想瀏覽器支援PUT、DELETE等請求方法只能模擬,稍候章節介紹。

2、除了GET、POST,還有HEAD、OPTIONS、PUT、DELETE、TRACE。

3、DispatcherServlet預設開啟對GET、POST、PUT、DELETE、HEAD的支援;

4、如果需要支援OPTIONS、TRACE,請新增DispatcherServlet在web.xml的初始化引數:dispatchOptionsRequest和 dispatchTraceRequest 為true。

請求方法的詳細使用請參考RESTful架構風格一章。

以上請求方法對映限定測試類為:cn.javass.chapter6.web.controller.method.RequestMethodController。

6.5.3、請求引數資料對映限定

6.5.3.1、請求資料中有指定引數名

Java程式碼  收藏程式碼
  1. package cn.javass.chapter6.web.controller.parameter;  
  2. //省略import  
  3. @Controller  
  4. @RequestMapping("/parameter1")                                      //①處理器的通用對映字首  
  5. public class RequestParameterController1 {  
  6.     //②進行類級別的@RequestMapping窄化  
  7.     @RequestMapping(params="create", method=RequestMethod.GET)   
  8.     public String showForm() {  
  9.         System.out.println("===============showForm");  
  10.         return "parameter/create";          
  11.     }  
  12.     //③進行類級別的@RequestMapping窄化  
  13.     @RequestMapping(params="create", method=RequestMethod.POST)    
  14.     public String submit() {  
  15.         System.out.println("================submit");  
  16.         return "redirect:/success";          
  17.     }  
  18. }  
 

@RequestMapping(params="create", method=RequestMethod.GET) :表示請求中有“create”的引數名且請求方法為“GET”即可匹配,如可匹配的請求URL“http://×××/parameter1?create”;

@RequestMapping(params="create", method=RequestMethod.POST):表示請求中有“create”的引數名且請求方法為“POST”即可匹配;

此處的create請求引數名表示你請求的動作,即你想要的功能的一個標識,常見的CRUD(增刪改查)我們可以使用如下請求引數名來表達:

create請求引數名  GET請求方法) 新增頁面展示、(create請求引數名  POST請求方法)新增提交;

update請求引數名  GET請求方法) 新增頁面展示、(update請求引數名  POST請求方法)新增提交;

delete請求引數名  GET請求方法) 新增頁面展示、(delete請求引數名  POST請求方法)新增提交;

query請求引數名  GET請求方法) 新增頁面展示、(query請求引數名  POST請求方法) 新增提交;

list請求引數名  GET請求方法) 列表頁面展示;

view請求引數名  GET請求方法) 檢視單條記錄頁面展示。

6.5.3.2、請求資料中沒有指定引數名

Java程式碼  收藏程式碼
  1. //請求引數不包含 create引數名  
  2. @RequestMapping(params="!create", method=RequestMethod.GET)//進行類級別的@RequestMapping窄化  

 @RequestMapping(params="!create", method=RequestMethod.GET):表示請求中沒有“create”引數名且請求方法為“GET”即可匹配,如可匹配的請求URL“http://×××/parameter1?abc”。

6.5.3.3、請求資料中指定引數名=值

Java程式碼  收藏程式碼
  1. package cn.javass.chapter6.web.controller.parameter;  
  2. //省略import  
  3. @Controller  
  4. @RequestMapping("/parameter2")                      //①處理器的通用對映字首  
  5. public class RequestParameterController2 {  
  6.     //②進行類級別的@RequestMapping窄化  
  7.     @RequestMapping(params="submitFlag=create", method=RequestMethod.GET)    
  8.     public String showForm() {  
  9.         System.out.println("===============showForm");  
  10.         return "parameter/create";          
  11.     }  
  12.     //③進行類級別的@RequestMapping窄化  
  13.     @RequestMapping(params="submitFlag=create", method=RequestMethod.POST)     
  14.     public String submit() {  
  15.         System.out.println("===============submit");  
  16.         return "redirect:/success";          
  17.     }  
  18. }  

 @RequestMapping(params="submitFlag=create", method=RequestMethod.GET):表示請求中有“submitFlag=create”請求引數且請求方法為“GET”即可匹配,如請求URL為http://×××/parameter2?submitFlag=create

@RequestMapping(params="submitFlag=create", method=RequestMethod.POST):表示請求中有“submitFlag=create”請求引數且請求方法為“POST”即可匹配;

此處的submitFlag=create請求引數表示你請求的動作,即你想要的功能的一個標識,常見的CRUD(刪改查)我們可以使用如下請求引數名來表達:

submitFlag=create請求引數名  GET請求方法) 新增頁面展示、(submitFlag=create請求引數名  POST請求方法) 新增提交;

submitFlag=update請求引數名  GET請求方法) 新增頁面展示、(submitFlag=update請求引數名  POST請求方法) 新增提交;

submitFlag=delete請求引數名  GET請求方法) 新增頁面展示、(submitFlag=delete請求引數名  POST請求方法) 新增提交;

submitFlag=query請求引數名  GET請求方法) 新增頁面展示、(submitFlag=query請求引數名  POST請求方法) 新增提交;

submitFlag=list請求引數名  GET請求方法) 列表頁面展示;

submitFlag=view請求引數名  GET請求方法) 檢視單條記錄頁面展示。

6.5.3.4、請求資料中指定引數名!=值

Java程式碼  收藏程式碼
  1. //請求引數submitFlag 不等於 create  
  2. @RequestMapping(params="submitFlag!=create", method=RequestMethod.GET)    

 @RequestMapping(params="submitFlag!=create", method=RequestMethod.GET):表示請求中的引數“submitFlag!=create”且請求方法為“GET”即可匹配,如可匹配的請求URL“http://×××/parameter1?submitFlag=abc”。

6.5.3.5、組合使用是“且”的關係

Java程式碼  收藏程式碼
  1. @RequestMapping(params={"test1", "test2=create"})  //②進行類級別的@RequestMapping窄化  

 @RequestMapping(params={"test1""test2=create"}):表示請求中的有“test1”引數名test2=create”引數即可匹配,如可匹配的請求URL“http://×××/parameter3?test1&test2=create。

以上請求引數資料對映限定測試類為:cn.javass.chapter6.web.controller.method包下的RequestParameterController1、RequestParameterController2、RequestParameterController3。

6.5.4、請求頭資料對映限定

6.5.4.1、準備環境

瀏覽器:建議chrome最新版本;

外掛:ModHeader

外掛安裝步驟:


圖6-2

2、點選“新增至chrome”後彈出“確認安裝”對話方塊,點選“安裝”按鈕即可,如圖6-3:


圖6-3

3、安裝成功後,在瀏覽器右上角出現如圖6-4的圖標表示安裝成功:


圖6-4

4、滑鼠右擊右上角的“Modify Header”圖示,選擇選項,開啟如圖6-5:


圖6-5

7、修改完成後,輸入URL請求,你可以在chrome的“開發人員工具的”網路選項卡下,看到如圖6-7的資訊表示新增請求頭成功了:


圖6-7

到此我們的工具安裝完畢,接下來看看如何使用請求頭資料進行對映限定。

6.5.4.2、請求頭資料中有指定引數名

@RequestMapping(value="/header/test1", headers = "Accept"):表示請求的URL必須為“/header/test1”

且 請求頭中必須有Accept引數才能匹配。

@RequestMapping(value="/header/test1", headers = "abc"):表示請求的URL必須為“/header/test1”

且 請求頭中必須有abc引數才能匹配,如圖6-8時可匹配。


圖6-8

6.5.4.3、請求頭資料中沒有指定引數名

@RequestMapping(value="/header/test2", headers = "!abc"):表示請求的URL必須為“/header/test2”

且 請求頭中必須沒有abc引數才能匹配。(將Modify Header的abc引數值刪除即可)。


6.5.4.4、請求頭資料中指定引數名=值

@RequestMapping(value="/header/test3", headers = "Content-Type=application/json"):表示請求的URL必須為“/header/test3” 且 請求頭中必須有“Content-Type=application/json”引數即可匹配。(將Modify Header的Content-Type引數值改為“application/json”即可);


當你請求的URL為“/header/test3  如果請求頭中沒有或不是“Content-Type=application/json”引數(如“text/html”其他引數),將返回“HTTP Status 415”狀態碼【表示不支援的媒體型別(Media Type),也就是MIME型別】,即我們的功能處理方法只能處理application/json的媒體型別。

@RequestMapping(value="/header/test4", headers = "Accept=application/json"):表示請求的URL必須為“/header/test4” 且 請求頭中必須有“Accept =application/json”引數即可匹配。(將Modify Header的Accept引數值改為“application/json”即可);


當你請求的URL為“/header/test4  如果請求頭中沒有“Accept=application/json”引數(如“text/html”其他引數),將返回“HTTP Status 406”狀態碼【不可接受,伺服器無法根據Accept頭的媒體型別為客戶端生成響應】,即客戶只接受“application/json”媒體型別的資料,即我們的功能處理方法的響應只能返回“application/json”媒體型別的資料。

@RequestMapping(value="/header/test5", headers = "Accept=text/*") :表示請求的URL必須為“/header/test5” 且 請求頭中必須有如“Accept=text/plain”引數即可匹配。(將Modify Header的Accept引數值改為“text/plain”即可);

Accept=text/*:表示主型別為text,子型別任意,如“text/plain”、“text/html”等都可以匹配。

@RequestMapping(value="/header/test6", headers = "Accept=*/*") :表示請求的URL必須為“/header/test6” 且 請求頭中必須有任意Accept引數即可匹配。(將Modify Header的Accept引數值改為“text/html”或“application/xml”等都可以)。

Accept=*/*:表示主型別任意,子型別任意,如“text/plain”、“application/xml”等都可以匹配。

6.5.4.5、請求頭資料中指定引數名!=值

@RequestMapping(value="/header/test7", headers = "Accept!=text/vnd.wap.wml"):表示請求的URL必須為“/header/test7” 且 請求頭中必須有“Accept”引數但值不等於“text/vnd.wap.wml”即可匹配。

6.5.4.6、組合使用是“且”的關係

@RequestMapping(value="/header/test8", headers = {"Accept!=text/vnd.wap.wml","abc=123"}):表示請求的URL必須為“/header/test8” 且 請求頭中必須有“Accept”引數但值不等於“text/vnd.wap.wml”且 請求中必須有引數“abc=123”即可匹配。

注:Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

如果您的請求中含有Accept:“*/*”,則可以匹配功能處理方法上的如“text/html”、“text/*”,“application/xml”等。