RequestMapping中consumes 和produces的作用
环境与参考资料
环境:spring 5.2.1 release,springboot 2.2.1.RELEASE
参考资料:HTTP 响应代码 - HTTP _ MDN
源码
先看源码
/**
* Narrows the primary mapping by media types that can be consumed by the
* mapped handler. Consists of one or more media types one of which must
* match to the request {@code Content-Type} header. Examples:
* <pre class="code">
* consumes = "text/plain"
* consumes = {"text/plain", "application/*"}
* consumes = MediaType.TEXT_PLAIN_VALUE
* </pre>
* Expressions can be negated by using the "!" operator, as in
* "!text/plain", which matches all requests with a {@code Content-Type}
* other than "text/plain".
* <p><b>Supported at the type level as well as at the method level!</b>
* If specified at both levels, the method level consumes condition overrides
* the type level condition.
* @see org.springframework.http.MediaType
* @see javax.servlet.http.HttpServletRequest#getContentType()
*/
String[] consumes() default {};
/**
* Narrows the primary mapping by media types that can be produced by the
* mapped handler. Consists of one or more media types one of which must
* be chosen via content negotiation against the "acceptable" media types
* of the request. Typically those are extracted from the {@code "Accept"}
* header but may be derived from query parameters, or other. Examples:
* <pre class="code">
* produces = "text/plain"
* produces = {"text/plain", "application/*"}
* produces = MediaType.TEXT_PLAIN_VALUE
* produces = "text/plain;charset=UTF-8"
* </pre>
* <p>If a declared media type contains a parameter (e.g. "charset=UTF-8",
* "type=feed", type="entry") and if a compatible media type from the request
* has that parameter too, then the parameter values must match. Otherwise
* if the media type from the request does not contain the parameter, it is
* assumed the client accepts any value.
* <p>Expressions can be negated by using the "!" operator, as in "!text/plain",
* which matches all requests with a {@code Accept} other than "text/plain".
* <p><b>Supported at the type level as well as at the method level!</b>
* If specified at both levels, the method level produces condition overrides
* the type level condition.
* @see org.springframework.http.MediaType
* @see org.springframework.http.MediaType
*/
String[] produces() default {};
源码中主要是这两句话
consumer:Narrows the primary mapping by media types that can be consumed by the mapped handler.
produces: Narrows the primary mapping by media types that can be produced by the mapped handler.
这两者都是和MediaType相关,而MediaType让我想到了 http协议request header中 content-type 和 Accept 字段的值。
consumer 和 produces 翻译就是消费者和生产者。这让我联想到生产者消费者模型,Http请求也是一个IO流的操作,肯定有输入和输出了,consumer和produces用在某个方法上时,应该指的就是该方法只能处理 consumer类型的input,produces类型的output了。
那么 这些字段相互的作用应该是这样的
- 如果 request header的content-type和方法中的consumer不匹配的话,那么该方法将无法处理。
- 如果 request header的accept和方法中的produces不匹配的话,那么该方法将无法处理。
Demo
处理方法
@PostMapping(value = "/hello",consumes = {"application/json"},produces = {"application/xml"})
@ResponseBody
public User hello(@RequestBody User user) {
System.out.println(user);
return user;
}
User类
import lombok.Data;
@Data
public class User {
private String name;
private Integer age;
}
request content-type为 application/x-www-form-urlencoded,accept不设置
后台无打印
response status 406
此情况是读取input数据就有问题了。
request content-type为 application/json,accept为不设置
request body
{
"name":"2",
"age":"1"
}
后台打印 User{name='2', age=1}
response status 406
response body
{
"timestamp": "2020-12-18T03:43:35.664+0000",
"status": 406,
"error": "Not Acceptable",
"message": "Could not find acceptable representation",
"path": "/hello"
}
此情况是读取input数据没有问题,写output出现问题。
request content-type为 application/json,accept为application/xml
request body
{
"name":"2",
"age":"1"
}
后台打印 User{name='2', age=1}
response status 406
response body 为空
此情况是读取input数据没有问题,写output出现问题。
解决方法
在UserBean 添加XmlRootElement注解。
import lombok.Data;
import javax.xml.bind.annotation.XmlRootElement;
@Data
@XmlRootElement
public class User {
private String name;
private Integer age;
}
再次请求
response status 200
response body
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user>
<age>1</age>
<name>2</name>
</user>
hello方法删除produces
request header为 application/json的请求返回json数据。
request header为 application/xml的请求返回xml数据。
总结
后端使用consumers和produces来指定当前方法处理 content-type和accept为什么的请求,前端使用accept告诉后端应该返回什么样的数据。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!
2017-12-18 Oracle 一条sql插入多条数据