@RequestMapping是Spring Web应用程序中最常被用到的注解之一。这个注解会将HTTP请求映射到MVC和REST控制器的处理方法上。
在这篇文章中,你将会看到@RequestMapping注解在被用来进行Spring MVC控制器方法的映射可以如何发挥其多才多艺的功能的。
一、Request Mapping基础用法
在 Spring MVC 应用程序中,RequestDispatcher (在 Front Controller 之下) 这个 servlet 负责将进入的 HTTP 请求路由到控制器的处理方法。
在对 Spring MVC 进行的配置的时候, 你需要指定请求与处理方法之间的映射关系。
要配置Web请求的映射,就需要你用上@RequestMapping注解。
@RequestMapping注解可以在控制器类的级别和/或其中的方法的级别上使用。
在类的级别上的注解会将一个特定请求或者请求模式映射到一个控制器之上。之后你还可以另外添加方法级别的注解来进一步指定到处理方法的映射关系。
下面是一个同时在类和方法上应用了@RequestMapping注解的示例:
如上述代码所示,到/home的请求会由get()方法来处理,而到/home/index的请求会由index()来处理。
二、@RequestMapping来处理多个URI
你可以将多个请求映射到一个方法上去,只需要添加一个带有请求路径值列表的@RequestMapping注解就行了。
如你在这段代码中所看到的,@RequestMapping支持统配符以及ANT风格的路径。前面这段代码中,如下的这些URL都会由indexMultipleMapping()来处理:
-
localhost:8080/home
-
localhost:8080/home/
-
localhost:8080/home/page
-
localhost:8080/home/pageabc
-
localhost:8080/home/view/
-
localhost:8080/home/view/view
三、带有@RequestParam的@RequestMapping
@RequestParam注解配合@RequestMapping 一起使用,可以将请求的参数同处理方法的参数绑定在一起。
@RequestParam注解使用的时候可以有一个值,也可以没有值。这个值指定了需要被映射到处理方法参数的请求参数, 代码如下所示:
在代码的第6行,id 这个请求参数被映射到了thegetIdByValue()这个处理方法的参数personId上。
如果请求参数和处理方法参数的名称一样的话,@RequestParam注解的value这个参数就可省掉了, 如代码的第11行所示。
@RequestParam注解的required这个参数定义了参数值是否是必须要传的。
在这段代码中,因为required被指定为false,所以getName()处理方法对于如下两个 URL 都会进行处理:
-
/home/name?person=xyz
-
/home/name
@RequestParam的defaultValue取值就是用来给取值为空的请求参数提供一个默认值的。
在这段代码中,如果person这个请求参数为空,那么getName()处理方法就会接收John这个默认值作为其参数。
四、用@RequestMapping处理HTTP的各种方法
Spring MVC的@RequestMapping注解能够处理HTTP请求的方法,比如GET, PUT, POST, DELETE以及PATCH。
所有的请求默认都会是HTTP GET类型的。
为了能降一个请求映射到一个特定的HTTP方法,你需要在@RequestMapping中使用method来声明HTTP请求所使用的方法类型,如下所示:
在上述这段代码中,@RequestMapping注解中的method元素声明了HTTP请求的HTTP方法的类型。
所有的处理处理方法会处理从这同一个URL( /home)进来的请求, 但要看指定的HTTP方法是什么来决定用哪个方法来处理。
例如,一个POST类型的请求/home会交给post()方法来处理,而一个DELETE类型的请求/home则会由delete()方法来处理。
你会看到Spring MVC将使用这样相同的逻辑来映射其它的方法。
用@RequestMapping来处理生产和消费对象
可以使用@RequestMapping注解的produces和consumes这两个元素来缩小请求映射类型的范围。
为了能用请求的媒体类型来产生对象, 你要用到@RequestMapping的produces元素再结合着@ResponseBody注解。
你也可以利用@RequestMapping的comsumes元素再结合着@RequestBody注解用请求的媒体类型来消费对象。
下面这段代码就用到的@RequestMapping的生产和消费对象元素:
在这段代码中,getProduces()处理方法会产生一个JSON响应,getConsumes()处理方法可以同时处理请求中的JSON和XML内容。
五、使用@RequestMapping来处理消息头
@RequestMapping注解提供了一个header元素来根据请求中的消息头内容缩小请求映射的范围。
在可以指定header元素的值,用myHeader = myValue这样的格式:
在上面这段代码中,@RequestMapping注解的headers属性将映射范围缩小到了post()方法。有了这个,post()方法就只会处理到/home/head并且content-typeheader被指定为text/plain这个值的请求。
你也可以像下面这样指定多个消息头:
这样,post()方法就能同时接受text/plain还有text/html的请求了。
五、使用@RequestMapping来处理请求参数
@RequestMapping直接的params元素可以进一步帮助我们缩小请求映射的定位范围。使用params元素,你可以让多个处理方法处理到同一个URL的请求, 而这些请求的参数是不一样的。
你可以用myParams = myValue这种格式来定义参数,也可以使用通配符来指定特定的参数值在请求中是不受支持的。
在这段代码中,getParams()和getParamsDifferent()两个方法都能处理相同的一个URL (/home/fetch) ,但是会根据params元素的配置不同而决定具体来执行哪一个方法。
例如,当URL是/home/fetch?id=10的时候, getParams()会执行,因为id的值是10,。对于localhost:8080/home/fetch?personId=20这个URL,getParamsDifferent()处理方法会得到执行,因为id值是 20。
六、使用@RequestMapping处理动态URI
@RequestMapping注解可以同@PathVaraible注解一起使用,用来处理动态的URI,URI的值可以作为控制器中处理方法的参数。你也可以使用正则表达式来只处理可以匹配到正则表达式的动态URI。
在这段代码中,方法getDynamicUriValue()会在发起到localhost:8080/home/fetch/10的请求时执行。这里getDynamicUriValue()方法id参数也会动态地被填充为10这个值。
方法getDynamicUriValueRegex()会在发起到localhost:8080/home/fetch/category/shirt的请求时执行。不过,如果发起的请求是/home/fetch/10/shirt的话,会抛出异常,因为这个URI并不能匹配正则表达式。
@PathVariable同@RequestParam的运行方式不同。你使用@PathVariable是为了从URI里取到查询参数值。换言之,你使用@RequestParam是为了从URI模板中获取参数值。
七、@RequestMapping默认的处理方法
在控制器类中,你可以有一个默认的处理方法,它可以在有一个向默认URI发起的请求时被执行。
下面是默认处理方法的示例:
在这段代码中,向/home发起的一个请求将会由default()来处理,因为注解并没有指定任何值。
八、@RequestMapping快捷方式
Spring 4.3引入了方法级注解的变体,也被叫做@RequestMapping的组合注解。组合注解可以更好的表达被注解方法的语义。它们所扮演的角色就是针对@RequestMapping的封装,而且成了定义端点的标准方法。
例如,@GetMapping是一个组合注解,它所扮演的是@RequestMapping(method =RequestMethod.GET)的一个快捷方式。
方法级别的注解变体有如下几个:
-
@GetMapping
-
@PostMapping
-
@PutMapping
-
@DeleteMapping
-
@PatchMapping
如下代码展示了如何使用组合注解:
在这段代码中,每一个处理方法都使用@RequestMapping的组合变体进行了注解。尽管每个变体都可以使用带有方法属性的@RequestMapping注解来互换实现, 但组合变体仍然是一种最佳的实践 — 这主要是因为组合注解减少了在应用程序上要配置的元数据,并且代码也更易读。
九、@RequestMapping总结
如你在本文中所看到的,@RequestMapping注解是非常灵活的。你可以使用该注解配置Spring MVC来处理大量的场景用例。它可以被用来在Spring MVC中配置传统的网页请求,也可以是REST风格的Web服务。
参考: