【转】Spring中的@RequestBody注解与常规的HTTP方法的传值方式
2021-05-11 02:30
标签:控件 字符串 类型信息 osi key image 意思 请求 种类型 地址:https://super-aviator.github.io/2019/08/30/Spring%E4%B8%AD%E7%9A%84-RequestBody%E6%B3%A8%E8%A7%A3/ 上周进行项目开发的时候,发现前端的含有文件的表单数据时后台接收报错,异常的大致意思是表单类型不支持,我也是有点蒙逼,以前也遇到过这种问题,加上@RequestBody就可以,所以这次我也加上了@RequestBody注解,结果还是报错,这时前端发消息过来,告诉我不能加@RequestBody,我去掉之后果然好了,好吧。一直没弄明白什么时候要加@RequestBody什么时候不要加,趁着这个迭代的任务很轻松,学习一下Spring中@RequestBody注解和后端如何接收常用的HTTP方法传过来的数据,结合PostMan对结果进行测试。 @RequestBody注解常用来处理POST请求,并且content-type不是默认的application/x-www-form-urlcoded编码的内容,比如说:application/json或者是application/xml等。一般情况下来说常用其来处理application/json类型。 @RequestMapping注解的方法的参数中包含了@RequestBody注解,那么Spring会首先查看请求中的Content-Type头部,然后根据Content-Type头部去查找合适的HttpMessageConverter 例如,如果客户端发送的Spittle数据是JSON表述形式,那 么Content-Type头部信息可能就会是“application/json”。在 这种情况下,DispatcherServlet会查找能够将JSON转换为Java 对象的消息转换器。如果Jackson 2库在类路径中,那 么MappingJackson2HttpMessageConverter将会担此重任,将 JSON表述转换为Spittle,然后传递到saveSpittle()方法中。 这个方法还使用了@ResponseBody注解,因此方法返回的Spittle 对象将会转换为某种资源表述,发送给客户端。 在《Spring 实战》中,表明了@RequestBody注解的含义和使用方式:用来解析请求体(可能是POST,PUT,DELETE,GET请求)中Content-Type为application/json类型的请求,利用消息转换器将其转换为对应的java对象(必须使用VO对象去接收),那么什么类型的消息能够加上@RequestBody,什么类型的消息不能加呢? MediaType,即是Internet Media Type,互联网媒体类型;也叫做MIME类型,在Http协议消息头中,使用Content-Type来表示具体请求中的媒体类型信息。Content-Type头部后面可以追加 Content-Type字段表明了请求的请求体类型,可以是如下几种常见的类型: 以application开头的媒体格式类型: 下面是常见的表单提交的Content-Type的取值: 如果使用的是GET请求,浏览器用 如果使用的是POST请求,会采用类似GET的字符串拼接的方式,将拼接的key-value字段放到body里面,而非url的后面,所以POST请求的url长度是没有限制的,因为拼接的url请求参数都存放在body里面,如下 注意:使用 如果没有type=file的控件,用默认的 上面的请求中,keyword键对应的值为panda,author键对应的值为zane。 首先我们看请求头的 Content-Type 它除了正常的 multipart/form-data 外还多了一个 boundary ,这个 boundary 的意思和字面意思一样就是分界线,通过分界线将每个键值对用 boundary 分割开来以示区别,这个分界线是特殊选择出来的,以便该boundary不会出现在任何有效负载中。现在我们看请求体,我们注意到boundary 将键值对分割后的每一部分都有 Content-Disposition 字段,实际上该字段的值必须为 form-data 而且后面必须加上 name 指定这部分的键名,然后是一行空行,空行之后便是提交数据的内容。 之所以要弄的这么复杂是因为 multipart/form-data 要支持文件上传。 注意:使用 数据以纯文本形式(text/json/xml/html)进行编码,POST方法使用这种方式会把表单的键值对以一个JSON字符串的方式放到HTTP的body里面。例如如下的postman中的请求示例: 注意:当非post请求的请求体中也含有JSON字符串时,依旧可以使用@RequestBody拿到请求体中的数据。 下面使用Postman来测试一下什么时候要加@Requestbody,什么时候不用加@RequestBody注解: 当请求中的ContentType分别为一下三种类型时,结果如下: @RequestBody用于需要触发HttpMessageConverter的场景: 注意:使用@RequestBody注解的参数必须使用VO对象的方式去接收,否则会接收不到参数 参考地址: 【转】Spring中的@RequestBody注解与常规的HTTP方法的传值方式 标签:控件 字符串 类型信息 osi key image 意思 请求 种类型 原文地址:https://www.cnblogs.com/lixiaoxu/p/13154112.html@RequestBody注解
表单类型
;charset=UTF-8
指定编码格式,例如:Content-Type:x-www-from-urlencoded;charset=UTF-8
常见媒体格式如下:
application/x-www-form-urlencoded
x-www-form-urlencoded
的编码方式把form数据转换成一个字串(name1=value1&name2=value2…),然后把这个字串append到url后面,用?分割,加载这个新的url。
1
2
3
4
5
6
7
POST HTTP/1.1
Host: 127.0.0.1:8000
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
Postman-Token: e8c31d7a-fd52-cbf2-2741-07d73cb1101b
keyword=panda&author=zaneapplication/x-www-form-urlencoded
编码方式的请求会对所有非ASCII的字符使用%HH的方式进行转换,所以一个非ASCII字符会由三个字符去表示,当非ASCII非常多时,会增加大约三倍的带宽,这无疑是一种浪费。multipart/form-data
application/x-www-form-urlencoded
就可以了。 但是如果有type=file的话,Content-Type就会升级使用multipart/form-data
类型。浏览器会把整个表单以控件为单位分割,并为每个部分加上Content-Disposition(form-data或者file),Content-Type(默认为text/plain),name(控件的name,即字段名)等信息,并加上分割符(boundary),例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST / HTTP/1.1
Host: 127.0.0.1:8000
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Cache-Control: no-cache
Postman-Token: 090df52c-d103-279b-1479-50e6a7fef58b
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="keyword"
panda
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="author"
zane
------WebKitFormBoundary7MA4YWxkTrZu0gWmultipart/form-data
编码方式的请求不会对非ASCII字符进行转码,所以也就不会有消耗,但是对于简短的字母数字值(与大多数web表单一样),添加所有MIME头的开销将大大超过更有效的二进制编码所节省的开销。application/json
?Postman测试
首先是Controller中的代码,有个方法,一个使用了@RequestBody注解,一个没有使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@RestController
@RequestMapping("/requestBody")
@Slf4j
public class RequestBodyController {
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
private static class Request{
private String name;
private Integer age;
@JSONField(serialize = false,deserialize = false)
private MultipartFile avatar;
}
@PostMapping("/request")
public HttpEntity
log.info("generalRequest-{}",JSON.toJSONString(request));
return new HttpEntity(request);
}
@PostMapping("/requestBody")
public HttpEntity
log.info("generalRequest-{}",JSON.toJSONString(request));
return new HttpEntity(request);
}
}
否加上注解\ContentType
x-www-form-urlencoded
form-data
application/json
不加@RequestBody注解
能接收
能接收
不能接收
加上@RequestBody注解
不能接收
不能接收
能接收
@RequestBody使用总结
HttpMessageConverter
或者自定义的HttpMessageConverter
对请求的body中的json字符串转换为java对象。
上一篇:python 锁
下一篇:Python 入门第十三天
文章标题:【转】Spring中的@RequestBody注解与常规的HTTP方法的传值方式
文章链接:http://soscw.com/index.php/essay/84197.html