在 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。