标签:控件 字符串 类型信息 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头部后面可以追加
;charset=UTF-8
指定编码格式,例如:Content-Type:x-www-from-urlencoded;charset=UTF-8
Content-Type字段表明了请求的请求体类型,可以是如下几种常见的类型:
常见媒体格式如下:
以application开头的媒体格式类型:
下面是常见的表单提交的Content-Type的取值:
如果使用的是GET请求,浏览器用x-www-form-urlencoded
的编码方式把form数据转换成一个字串(name1=value1&name2=value2…),然后把这个字串append到url后面,用?分割,加载这个新的url。
如果使用的是POST请求,会采用类似GET的字符串拼接的方式,将拼接的key-value字段放到body里面,而非url的后面,所以POST请求的url长度是没有限制的,因为拼接的url请求参数都存放在body里面,如下
1
|
POST HTTP/1.1
|
注意:使用application/x-www-form-urlencoded
编码方式的请求会对所有非ASCII的字符使用%HH的方式进行转换,所以一个非ASCII字符会由三个字符去表示,当非ASCII非常多时,会增加大约三倍的带宽,这无疑是一种浪费。
如果没有type=file的控件,用默认的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
|
POST / HTTP/1.1
|
上面的请求中,keyword键对应的值为panda,author键对应的值为zane。
首先我们看请求头的 Content-Type 它除了正常的 multipart/form-data 外还多了一个 boundary ,这个 boundary 的意思和字面意思一样就是分界线,通过分界线将每个键值对用 boundary 分割开来以示区别,这个分界线是特殊选择出来的,以便该boundary不会出现在任何有效负载中。现在我们看请求体,我们注意到boundary 将键值对分割后的每一部分都有 Content-Disposition 字段,实际上该字段的值必须为 form-data 而且后面必须加上 name 指定这部分的键名,然后是一行空行,空行之后便是提交数据的内容。 之所以要弄的这么复杂是因为 multipart/form-data 要支持文件上传。
注意:使用multipart/form-data
编码方式的请求不会对非ASCII字符进行转码,所以也就不会有消耗,但是对于简短的字母数字值(与大多数web表单一样),添加所有MIME头的开销将大大超过更有效的二进制编码所节省的开销。
数据以纯文本形式(text/json/xml/html)进行编码,POST方法使用这种方式会把表单的键值对以一个JSON字符串的方式放到HTTP的body里面。例如如下的postman中的请求示例:
?
注意:当非post请求的请求体中也含有JSON字符串时,依旧可以使用@RequestBody拿到请求体中的数据。
下面使用Postman来测试一下什么时候要加@Requestbody,什么时候不用加@RequestBody注解:
首先是Controller中的代码,有个方法,一个使用了@RequestBody注解,一个没有使用:
1
|
|
当请求中的ContentType分别为一下三种类型时,结果如下:
否加上注解\ContentType | x-www-form-urlencoded | form-data | application/json |
---|---|---|---|
不加@RequestBody注解 | 能接收 | 能接收 | 不能接收 |
加上@RequestBody注解 | 不能接收 | 不能接收 | 能接收 |
@RequestBody用于需要触发HttpMessageConverter的场景:
HttpMessageConverter
或者自定义的HttpMessageConverter
对请求的body中的json字符串转换为java对象。注意:使用@RequestBody注解的参数必须使用VO对象的方式去接收,否则会接收不到参数
参考地址:
【转】Spring中的@RequestBody注解与常规的HTTP方法的传值方式
标签:控件 字符串 类型信息 osi key image 意思 请求 种类型
原文地址:https://www.cnblogs.com/lixiaoxu/p/13154112.html