在 POJO 類定義處標注 @Controller,再通過 <context:component-scan/> 掃描相應的類包,即可使 POJO 成為一個能處理 HTTP 請求的控制器。
用戶可以創建數量不限的控制器。每個控制器可擁有多個處理請求的方法,每個方法負責不同的請求操作。如何將請求映射到對應的控制器方法中是 Spring MVC 框架的重要任務之一,這項任務由 @RequestMapping 承擔。
在控制器的類定義及方法定義處都可以標注 @RequestMapping,類定義處的 @RequestMapping 提供初步的請求映射信息,方法定義處的 @RequestMapping 提供進一步的細分映射信息。DispatcherServlet 截獲請求后,就通過控制器上 @RequestMapping 提供的映射信息確定請求所對應的處理方法。
將請求映射到控制器處理方法的工作包含一系列映射規則,這些規則是根據請求中的各種信息制定的,具體包括請求URL、請求參數、請求方法、請求頭這4個方面的信息項。
1.通過請求URL進行映射
@RequestMapping 使用 value 值指定請求的URL,如 @RequestMapping("/user")、@RequestMapping("/register") 等。需要注意的是,@RequestMapping 在類定義處指定的 URL 相對於 Web 應用的部署路徑,而在方法定義處指定的 URL 則相對於類定義處指定的 URL,如果在類定義處未標注 @RequestMapping,則僅在處理方法處標注 @RequestMapping,此時,方法處指定的 URL 則相對於Web 應用的部署路徑。
同一控制器的多個處理方法負責處理相同業務模塊的不同操作,但凡設計合理的 web 應用都會將這些操作請求安排在某一相同的 URL 之下。所以除非特別的原因,建議不要舍棄類定義處的@RequestMapping。
@RequestMapping 不但支持標准的 URL,還支持 Ant 風格和帶 {xxx} 占位符的 URL。
以下 URL都是合法的。
1)/user/*/createUser:匹配 /user/aaa/createUser、/user/bbb/createUser 等 URL
2)/user/**/createUser:匹配 /user/createUser、/user/aawbbb/createUser 等 URL
3)/user/createUser??:匹配 /user/createUseraa、/user/createUserbb 等 URL
4)/user/{userld}:匹配 user/123、user/456 等 URL
5)/user/**/{userld}:匹配 user/aaa/bbb/123、user/aaa/456 等 URL
6)company/{companyld}/user/{userld}/detail:匹配 company/123/user/456/detaiI 等 URL
通過 @PathVariable 可以將 URL 中的占位符參數綁定到控制器處理方法的入參中,如下代碼所示。
@Controller @RequestMapping("/user") public class UserController { @RequestMapping(value="/{userId}") public ModelAndView showDetail(@PathVariable("userId") String userId){ ModelAndView mav = new ModelAndView(); mav.setViewName("user/showDetail"); mav.addObject("user", userService.getUserById(userId)); return mav; } }
URL 中的 {xxx} 占位符可以通過 @PathVanable(''xxx")綁定到操作方法的入參中。類定位處 @RequestMapping的 URL 如果使用占位符的參數,則也可以綁定到處理方法的入參中。
2.通過請求參數、請求方法或請求頭進行映射
HTTP 請求報文除 URL 外,還擁有其他眾多的信息。以下是一個標准的 HTTP 請求報文,如下圖所示。
①是請求方法,GET 和 POST 是最常見的 HTTP 方法,除此以外還包括 DELETE、HEAD、OPTIONS、PUT、TRACE。不過,當前的大多數瀏覽器只支持 GET 和 POST,Spring 提供了一個 HiddenHttpMethodFilter,允許通過 method 表單參數指定這些特殊的 HTTP 方法(實際上還是通過 POST 提交表單)。服務器端配置了 HiddenHttpMethodFilter 后,Spring 會根據 method 參數指定的值模擬出相應的 HTTP 方法,這樣就可以使用這些 HTTP 方法對處理方法進行映射了。
②是請求對應的 URL 地址,它和報文頭的 Host 屬性組成完整的請求 URL
③是協議名稱及版本號。
④是 HTTP 的報文頭,報文頭包含若干個屬性,格式為“屬性名:屬性值”,服務器端據此獲取客戶端的信息。
⑤是報文體,它將一個頁面表單中的組件值通過 param1=value1¶m2=value2 的鍵值對形式編碼成一個格式化串,它承載多個請求參數的數據。不但報文體可以傳遞請求參數,請求 URL 也可以通過類似於 /chapterl7/user.html?paraml1=value1¶m2=value2 的方式傳遞請求參數。
@RequestMapping 除了可以使用請求 URL 映射請求外,還可以使用請求方法、請求頭參數及請求參數(報文體和 URL 包含的請求參數)映射請求,如下面代碼所示。
@Controller @RequestMapping("/user") public class UserController { @RequestMapping(value = "/delete", method = RequestMethod.POST, params = "userId") public String test1(@RequestParam("userId") String userId) { // do sth return "user/test1"; } @RequestMapping(value = "/show", headers = "content-type=text/*") public String test2(@RequestParam("userId") String userId) { // do sth return "user/test2"; } }
@RequestMapping 的 value、method、params 及 headers 分別表示請求URL、請求方法、請求參數及報文頭的映射條件,它們之間是與的關系,聯合使用多個條件項可讓請求映射更加精確化。
params 和 headers 分別通過請求參數及報文頭屬性進行映射,它們支持簡單的映射表達式。下面以 params 表達式為例進行說明,headers 可以參照來理解。
1)"param1":表示請求須包含名為 param1 的請求參數。
2)"!param1":表示請求不能包含名為 param1 的請求參數。
3)"param1!=value1":表示請求包含名為 param1 的請求參數,但其值不能為 value1。
4){"param1=value1","param2"}:表示請求必須包含名為 param1和 param2 的兩個請求參數,且 param1 參數的值必須為 value1。