Spring Web Annotations



原文地址:http://www.baeldung.com/spring-mvc-annotations 此篇为译文,由于英语水平有限,可能对原文的理解有误,欢迎指正,不甚感激!

1. 概览

在本篇教程中,我们将要探讨Spring web开发有关的注解(Spring MVC注解),这些注解存在于org.springframework.web.bind.annotation包中。

2. @RequestMapping

简而言之,@RequestMapping标记@Controller类中的请求处理器(request handler)方法。可用的配置有: - path:或者别名namevalue都可以作为参数名,它指定了哪个URL映射到当前的方法。 - method:协调处理HTTP请求的方法。 - params:根据HTTP请求参数的存在、不存在或者值来过滤请求。 - headers:根据HTTP请求的headers的存在、不存在或者值来过滤请求。 - consumes:限制哪些HTTP请求主体中的媒体类型可以被该方法使用。 - produces:限制改方法可以响应哪些HTTP媒体类型。

来看一个简单的例子:

1
2
3
4
5
6
7
8
@Controller
class VehicleController {
 
    @RequestMapping(value = "/vehicles/home", method = RequestMethod.GET)
    String home() {
        return "home";
    }
}

如果我们在类级别上应用此注释,我们可以为@Controller类中的所有处理程序方法(request handler)提供默认设置。唯一的区别就是Spring在寻找URL映射的时候,不仅仅只看方法或者类上面的配置,而是会结合起来:

1
2
3
4
5
6
7
8
9
@Controller
@RequestMapping(value = "/vehicles", method = RequestMethod.GET)
class VehicleController {
 
    @RequestMapping("/home")
    String home() {
        return "home";
    }
}

此外,可以使用@GetMapping@PostMapping@PutMapping@DeleteMapping以及@PatchMapping这些不同的@RequestMapping变种,可以单独的设置GETPOSTPUTDELETEPATCH请求。

这些是在Spring4.3版本以后可用的。

3. @RequestBody

使用@RequestBody注解可以将HTTP请求body体映射到一个对象:

1
2
3
4
@PostMapping("/save")
void saveVehicle(@RequestBody Vehicle vehicle) {
    // ...
}

反序列化是自动的,当然着取决于请求的content type的类型。

4. @PathVariable

接下来,我们来谈谈@PathVariable

此注解表示将方法参数绑定到URI模板变量。我们可以使用@RequestMapping注解指定URI模板变量,然后使用@PathVariable指定需要绑定的方法参数。

我们可以使用name或者别名绑定,有value参数的例子:

1
2
3
4
@RequestMapping("/{id}")
Vehicle getVehicle(@PathVariable("id") long id) {
    // ...
}

如果方法的参数名和URI模板变量的名称一致,那么我们就不需要在@PathVariable注解中指定了:

1
2
3
4
@RequestMapping("/{id}")
Vehicle getVehicle(@PathVariable long id) {
    // ...
}

此外,我们还可以标记这个URI模板变量是不是必需的:

1
2
3
4
@RequestMapping("/{id}")
Vehicle getVehicle(@PathVariable(required = false) long id) {
    // ...
}

5. @RequestParam

我们可以使用@RequestParam注解访问HTTP请求参数:

1
2
3
4
@RequestMapping
Vehicle getVehicleByParam(@RequestParam("id") long id) {
    // ...
}

@RequestParam注解的配置选项和PathVariable注解一致。

除了一致的配置以外,当Spring从绑定的HTTP请求参数中获得了一个空值,或者根本没找到这个参数的时候,@RequestParam还可以为方法参数设置一个默认值,为了实现这一点,我们需要使用defaultValue这个参数:

提供默认的值的情况下,required参数会被设置为false(博主注:也就是无论如何都赋一个值):

1
2
3
4
@RequestMapping("/buy")
Car buyCar(@RequestParam(defaultValue = "5") int seatCount){
    // ...
}

除了访问HTTP请求的参数,像HTTP请求中的其他数据也可以访问到:cookiesheaders,访问它们可以使用另外两个注解@CookieValue@RequestHeader。可以像使用@RequestParam一样来配置这两个注解。

6. 响应相关的注解

6.1. @ResponseBody

如果我们对一个请求处理器(request handler)方法使用@ResponseBody注解,那么Spring会把这个方法的返回值当作响应本身(博主注:也就是不会当作视图名称返回,当作rest API使用可以返回json数据):

1
2
3
4
5
@ResponseBody
@RequestMapping("/hello")
String hello() {
    return "Hello World!";
}

如果我们在@Controller类上使用@ResponseBody注解,那么其内部所有的请求处理器(request handler)方法都会生效。

6.2. @ExceptionHandler

使用这个注解,我们可以声明一个自定义的错误处理器(error handler)方法。当请求处理器(request handler)方法抛出任何指定的异常时,Spring会调用此自定义方法。

被捕获的异常可以作为参数传递给方法:

1
2
3
4
@ExceptionHandler(IllegalArgumentException.class)
void onIllegalArgumentException(IllegalArgumentException exception) {
    // ...
}

博主注:上面的方法定义了一个处理IllegalArgumentException类型异常的方法,当任何的请求处理器(request handler)方法抛出这个异常,就会自动执行该方法。

6.3. @ResponseStatus

如果我们使用@ResponseStatus注解标注一个请求处理器(request handler)方法,则可以自定义一个期望返回的HTTP状态码。我们可以使用code参数声明状态码,或者别名也可以。

另外,我们也可以使用reason参数提供一个“reason”。

可以在@ExceptionHandler方法上使用@ResponseStatus

1
2
3
4
5
@ExceptionHandler(IllegalArgumentException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST,reason = "用户名和密码不匹配!")
void onIllegalArgumentException(IllegalArgumentException exception) {
    // ...
}

博主注:reason会在返回的响应体中出现。

7. 其他Web相关注解

一些注解并不能直接的管理HTTP请求或者响应,在这一节中,我们将介绍这种最常见的注解。

7.1. @RestController

@RestController注解合并了@Controller@ResponseBody这两个注解的功能。(博主注:也就是实现rest API的关键)

因此,下面这两组代码实现的功能是相同的:

1
2
3
4
5
@Controller
@ResponseBody
class VehicleRestController {
    // ...
}
1
2
3
4
@RestController
class VehicleRestController {
    // ...
}

7.2. @ModelAttribute

通过这个注解我们可以通过设置的数据模型(model)key访问已经在MVC控制器中的数据模型(model):

1
2
3
4
@PostMapping("/assemble")
void assembleVehicle(@ModelAttribute("vehicle") Vehicle vehicleInModel) {
    // ...
}

类似@PathVariable@RequestParam注解,我们如果方法参数名和数据模型(model)key一致,就可省略:

1
2
3
4
@PostMapping("/assemble")
void assembleVehicle(@ModelAttribute Vehicle vehicle) {
    // ...
}

除了这些,@ModelAttribute还有另外一个地方会用到:如果我们在一个方法上标注,Spring会自动将方法的返回值添加到这个数据模型(model)中:

1
2
3
4
@ModelAttribute("vehicle")
Vehicle getVehicle() {
    // ...
}

类似的,如果方法名和数据模型(model)key一致,那么也可以省略这个key

1
2
3
4
@ModelAttribute
Vehicle vehicle() {
    // ...
}

Spring在调用请求处理器(request handler)方法之前,他会先调用该类中所有的@ModelAttribute注解方法。

更多关于@ModelAttribute注解的信息,可以阅读这篇文章

7.3. @CrossOrigin

@CrossOrigin注解可以在请求处理器(request handler)方法上启用允许跨域请求:

1
2
3
4
5
@CrossOrigin
@RequestMapping("/hello")
String hello() {
    return "Hello World!";
}

如果我们标记在一个类上,那么该类下面的所有请求处理器(request handler)方法都会允许跨域请求。

我们可以用这个注解的参数来微调CORS行为。

更多的信息,请查阅这篇文章

8. 总结

在这片文章中,我们展现了怎么在Spring MVC中处理HTTP请求和响应,同样,文章中的示例代码可以在我们的GitHub上获得。