【Spring MVC】@RequestMapping 详解

@RequestMapping注解一共有8个属性,常用的有value属性、method属性,其它6个属性往往容易被忽视,因此本文将逐一介绍这8个属性的作用及用法

示例代码依赖版本如下
Spring Boot:3.0.0-SNAPSHOT
Spring MVC:6.0.0-SNAPSHOT
server.port=8181

1.源代码

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
@Reflective({ControllerMappingReflectiveProcessor.class})
public @interface RequestMapping {
    String name() default "";

    @AliasFor("path")
    String[] value() default {};

    @AliasFor("value")
    String[] path() default {};

    RequestMethod[] method() default {};

    String[] params() default {};

    String[] headers() default {};

    String[] consumes() default {};

    String[] produces() default {};
}

以下按照源码中属性的顺序介绍(value最重要,先介绍value属性)

2.value属性

@GetMapping("/value")
public String demoValue() {
    return "value";
}

访问 http://127.0.0.1:8181/value 即可执行方法

@GetMapping(value = {"/foo", "/bar"})
public String demoValue() {
    return "value";
}

访问 http://127.0.0.1:8181/foo 或 http://127.0.0.1:8181/bar 均执行该方法

3.path属性

作用同value,path、value可同时使用(不推荐),但是值必须一致
反例(两者值不相同):

@GetMapping(value = "/path", path = "/path2")
public String demoPath() {
    return "path";
}

运行报错

Different @AliasFor mirror values for annotation [org.springframework.web.bind.annotation.GetMapping] declared on com.example.springbootssl.controller.TestController.demoPath1(); attribute ‘path’ and its alias ‘value’ are declared with values of [{/path2}] and [{/path}].

4.name属性

@GetMapping(value = "/name", name = "name属性演示")
public String demoName() {
    return "name";
}

相当于方法的注释,无实际作用

5.method属性

用于设置HTTP请求方法,如GET、POST、PUT、DELETE等,类型为RequestMethod枚举类数组

public enum RequestMethod {
    GET,
    HEAD,
    POST,
    PUT,
    PATCH,
    DELETE,
    OPTIONS,
    TRACE;

    private RequestMethod() {
    }
}

示例代码

@RequestMapping(value = "/method", method = RequestMethod.GET)
public String demoMethod() {
    return "method";
}

该方法需要通过GET请求来调用,在Spring4.3后可以使用@GetMapping、@PostMapping之类的注解简化编码

@GetMapping("/method")
public String demoMethod() {
    return "method";
}

@RequestMapping替换成@GetMapping,method属性直接不用写,两者是等价的,但后者更简洁

也可以让方法同时支持多种请求、如同时支持GET和POST,这种情况就无法使用简化的注解了

@RequestMapping(value = "/method", method = {RequestMethod.GET, RequestMethod.POST})
 public String demoMethod() {
     return "method";
 }

6.params属性

请求参数包含指定的key和value时,才能执行请求

@GetMapping(value = "/params", params = "par=foo")
public String demoParams(@RequestParam String par) {
    System.out.println("par = " + par);
    return "params";
}

请求参数par的值必须为foo时才可执行该方法
若访问http://127.0.0.1:8181/params?par=bar
则HTTP状态码为400,异常信息如下:

Resolved [org.springframework.web.bind.UnsatisfiedServletRequestParameterException: Parameter conditions “par=foo” not met for actual request parameters: par={bar}]

若指定多个参数,则用String数组的形式

@GetMapping(value = "/params", params = {"par=foo", "par2=bar"})
public String demoParams(@RequestParam String par, @RequestParam String par2) {
	// ...
}

必须同时满足条件,即par=foo,par2=bar才执行请求

7.headers属性

和params的作用十分相似,请求头包含指定的key和value时,才能执行请求

@GetMapping(value = "/headers", headers = "X-key=foobar")
public String demoHeaders() {
    return "headers";
}

此时请求头必须含有X-key且值为foobar才能执行请求
使用工具手动添加header发送请求,调用成功在这里插入图片描述
要注意的是,若不符合条件返回HTTP状态码是404而不是400

8.consumes属性

当请求提交的内容MIME类型和consumes指定的一致时,才执行方法,否则返回415状态码(Unsupported Media Type)

示例代码

@PostMapping(value = "/consumes", consumes = "application/json")
public Map<String, Object> demoConsumes(@RequestBody Map<String, Object> map) {
    return map;
}

上述代码只有提交内容为MIME类型为application/json时,才执行方法,也就是说请求头中的Content-Type是由客户端决定的,假设为application/json,但客户端实际传的是xml格式的数据,此时由于consumes属性为application/json,两者类型不统一,因此不执行方法

在这里插入图片描述
反例(传入数据的MIME类型和指定的不一致):

@PostMapping(value = "/consumes", consumes = "application/xml")
public Map<String, Object> demoConsumes(@RequestBody Map<String, Object> map) {
    return map;
}

这时body必须传xml格式的才会被处理。故意传json格式的数据,将报如下错
在这里插入图片描述
此时HTTP状态码为415,也就是Unsupported Media Type

正确使用:传入xml格式的数据
在此之前,需要先搞清楚Spring MVC接收xml格式数据的方法,因为大部分都是接收JSON格式的body,直接使用@RequestBody即可,而xml也是使用该注解,但需要额外引入一个依赖,让Jackson支持xml解析

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

在这里插入图片描述
调用成功,传入xml数据,返回json数据

9.produces属性

作用是指定响应头中Content-Type的值
简单说就是指定返回数据的MIME类型,且仅当请求头中的Accept包含该指定类型才返回(否则返回 406状态码 Not Acceptable)

因此,客户端需要什么类型的数据,通过Accept请求头就能指定,Accept为image/*,那么服务端就必须返回图片类型的数据,若Accept为 * / *,则服务端可以返回任意MIME类型的数据了。

@GetMapping(value = "/produces", produces = "application/xml")
public Map<String, Object> demoProduces() {
    Map<String, Object> map = new LinkedHashMap<>(3);
    map.put("name", "zhangsan");
    map.put("sex", "male");
    map.put("age", 18);
    return map;
}

produces为application/xml,返回xml格式的数据

<Map>
    <name>zhangsan</name>
    <sex>male</sex>
    <age>18</age>
</Map>

produces为application/json,返回json格式的数据

{
	"name": "zhangsan",
	"sex": "male",
	"age": 18
}

produces 并非指定什么MIME类型,就返回什么MIME类型的数据,直接返回传入的xml格式数据,而produces = “application/pdf”,显然是不合理的,会报以下错误:

No converter for [class …] with preset Content-Type ‘null’]

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值