Java充电社
专辑
博文
联系我
本人继续续收门徒,亲手指导
SpringMVC教程
-> @RequestBody原理解密
1、Helloword
2、@Controller、@RequestMapping
3、接口测试利器
4、如何接受请求中的参数?
5、@RequestBody接收Json格式数据
6、多文件上传
7、返回页面常见的5种方式
8、返回json格式数据 & 通用返回值设计
9、SpringMVC返回null是什么意思?
10、异步处理请求
11、如何集成静态资源?
12、拦截器怎么用?
13、统一异常处理
14、实战篇:通用返回值 & 异常处理设计
15、全注解的方式 & 原理解析
16、源码解析SpringMVC处理请求的流程
17、源码解析SpringMVC容器的启动过程
18、RequestBodyAdvice:对@ReuqestBody进行增强
19、ResponseBodyAdvice:对@ResponseBody进行增强
20、RESTful接口详解
21、接口调用利器RestTemplate
22、参数解析器HandlerMethodArgumentResolver解密
23、@RequestParam用法及原理详解
24、@RequestBody原理解密
25、@RequestHeader详解
26、@CookieValue详解
27、@RequestAttribute详解
28、@SessionAttribute详解
29、重定向和转向详解
30、Converter转换器详解
31、跨域问题详解
32、类容协商,颠覆你的认知
33、终章
34、CORS通信
35、浏览器安全策略 & CORS
36、Http中的Content-Type详解
上一篇:@RequestParam用法及原理详解
下一篇:@RequestHeader详解
<div style="display:none"></div> **大家好,我是路人,这是SpringMVC系列第24篇。** 本文将介绍@RequestBody注解常见的一些用法和原理,这个注解日常用到的特别多。 ## 1、预备知识 1. <a href="https://mp.weixin.qq.com/s/83zvde-O5PlI9Vd2nP_PZQ" target="_blank">接口测试利器 HTTP Client</a> 2. <a href="https://mp.weixin.qq.com/s/XQ1K4eXtGvfG_0RReFVg8Q" target="_blank">参数解析器HandlerMethodArgumentResolver解密</a> ## 2、@RequestBody介绍 标注在接口的参数上,用来获取HTTP请求body中的值,下面通过案例列出常见的用法。 ```java @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RequestBody { /** * body是不是必须的,默认为true,若不传body,会有异常;若为false,这body可不传 */ boolean required() default true; } ``` **推荐阅读:**[尚硅谷 Java 学科全套教程(总 207.77GB)](https://mp.weixin.qq.com/s?__biz=MzkzOTI3Nzc0Mg==&mid=2247484964&idx=2&sn=c81bce2f26015ee0f9632ddc6c67df03&scene=21#wechat_redirect) ## 3、案例1:使用字符串接收body中的数据 ### 3.1、接口代码 > 注意方法的参数,使用@RequestBody标注,参数类型是String,表示以字符串的方式接收body的数据。 ```java @RequestMapping("/requestbody/test1") public String test1(@RequestBody String body) { System.out.println("body:" + body); return "ok"; } ``` 下面来模拟发送5种格式的数据,然后看控制台的输出。 ### 3.2、用例1:发送纯文本数据 > Content-Type用来指定客户端发送的数据的类型。 ```java ### 发送纯文本 POST http://localhost:8080/chat18/requestbody/test1 Content-Type: text/plain 这里是body部分,欢迎访问我的博客:itsoku.com,上面有更多系列文章 ``` 运行,接口内部控制台输出 ```java body:这里是body部分,欢迎访问我的博客:itsoku.com,上面有更多系列文章 ``` ### 3.3、用例2:发送表单数据,相当于提交表单 > Content-Type: application/x-www-form-urlencoded 相当于页面中提交表单,表单中的所有元素会以name=value&name=value的方式拼接起来,然后在进行urlencoded,之后丢在body中发送。 ```java ### 发送表单数据,相当于提交表单 POST http://localhost:8080/chat18/requestbody/test1 Content-Type: application/x-www-form-urlencoded name=路人&blogs=itsoku.com ``` 运行输出如下,可以看出来是乱码的格式,是由于被中文被urlencoded编码了。 ``` body:name=%E8%B7%AF%E4%BA%BA&blogs=itsoku.com ``` ### 3.4、用例3:发送xml数据 ```java ### 发送xml数据 POST http://localhost:8080/chat18/requestbody/test1 Content-Type: text/xml <CourseList> <Course>Java高并发系列</Course> <Course>MyBatis系列</Course> <Course>MySQL系列</Course> <Course>Spring高手系列</Course> <Course>分布式事务高手系列</Course> </CourseList> ``` 运行,控制台输出 ```java body:<CourseList> <Course>Java高并发系列</Course> <Course>MyBatis系列</Course> <Course>MySQL系列</Course> <Course>Spring高手系列</Course> <Course>分布式事务高手系列</Course> </CourseList> ``` ### 3.5、用例4:发送json数据 ```java ### 发送json数据 POST http://localhost:8080/chat18/requestbody/test1 Content-Type: application/json;charset=UTF-8 { "blog": "itsoku.com", "course": [ "Spring高手系列", "MySQL系列", "高并发系列" ] } ``` 运行,控制台输出 ```java body:{ "blog": "itsoku.com", "course": [ "Spring高手系列", "MySQL系列", "高并发系列" ] } ``` 从上面可以看出,接口参数body的值为http请求body中的原始数据。 **推荐阅读:**[2021 最新版 Java 微服务学习线路图 + 视频](https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484192&idx=1&sn=505f2faaa4cc911f553850667749bcbb&scene=21#wechat_redirect) ## 4、案例2:使用对象接收json格式的数据 ### 4.1、用法 发送json格式的数据,这种用到的比较多,http请求发送这种数据,有3点要求: 1. Content-Type的值需要为:application/json;charset=UTF-8,告诉服务器端客户端body中的数据是json格式 & UTF-8编码 2. body中数据为json格式 3. 接口端用对象接收,参数使用@RequestBody标注 ### 4.2、接口代码 ```java @RequestMapping("/requestbody/test2") public String test2(@RequestBody User user) { System.out.println("user:" + user); return "ok"; } ``` User类 ```java public class User { private String name; private Integer age; private List<String> skills; //省略get、set @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + ", skills=" + skills + '}'; } } ``` ### 4.3、调用接口 重点注意了,头中需要加上`Content-Type: application/json` ```java ### 发送json数据,后端用对象接收 POST http://localhost:8080/chat18/requestbody/test2 Content-Type: application/json;charset=UTF-8 { "name": "路人", "age": 35, "skills": [ "高并发", "Spring", "分布式事务", "MQ", "MySQL" ] } ``` ### 4.4、控制台输出 ```java user:User{name='路人', age=35, skills=[高并发, Spring, 分布式事务, MQ, MySQL]} ``` **推荐阅读:**[阿里技术大佬整理的《Spring 学习笔记.pdf》](https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484573&idx=1&sn=7f3d83892186c16c57bc0b99f03f1ffd&scene=21#wechat_redirect) ## 5、案例3:使用Resource资源对象接收 ### 5.1、用法 有时候,我们想以流的方式接收body中的数据,那么可以参考下面的写法,参数类型为`[ByteArrayResource,InputStreamResource]这2种类型即可`,第一种类型获取的是一个字节数组,第二个是一个InputStream输入流。 比如我们需要快速上传文件到阿里云,那么接口接收到客户端的流之后,直接将流转发到oss,效率更高。 ```java /** * 参数为如果为 org.springframework.core.io.Resource 类型, * 则只能为Resource的[ByteArrayResource,InputStreamResource]这2种子类型: * * @param body * @return * @throws IOException */ @RequestMapping("/requestbody/test3") public String test3(@RequestBody InputStreamResource body) throws IOException { String content = IOUtils.toString(body.getInputStream(), "UTF-8"); System.out.println("content:" + content); return "ok"; } ``` ### 5.2、调用接口 ```java ### 后端使用Resource接收数据 POST http://localhost:8080/chat18/requestbody/test3 Content-Type: text/plain;charset=UTF-8 后端使用Resource接收数据 ``` ### 5.3、控制台输出 ```java content:后端使用Resource接收数据 ``` **推荐阅读:**[阿里大佬的《MySQL 学习笔记高清.pdf》](https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484544&idx=2&sn=c1dfe907cfaa5b9ae8e66fc247ccbe84&scene=21#wechat_redirect) ## 6、案例4:以字节数组接受数据 ### 6.1、代码 ```java /** * 使用字节数组接收 * * @param bodyBytes * @return */ @RequestMapping("/requestbody/test4") public String test4(@RequestBody byte[] bodyBytes) { System.out.println("body长度(bytes):" + bodyBytes.length); System.out.println("body内容:" + new String(bodyBytes)); return "ok"; } ``` ### 6.2、调用接口 ```java ### 后端使用字节数组接收数据 POST http://localhost:8080/chat18/requestbody/test4 Content-Type: text/plain;charset=UTF-8 itsoku.com ``` ### 6.3、控制台输出 ```java body长度(bytes):10 body内容:itsoku.com ``` **推荐阅读:**[2021 版 java 高并发常见面试题汇总.pdf](https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485167&idx=1&sn=48d75c8e93e748235a3547f34921dfb7&scene=21#wechat_redirect) ## 7、案例5:使用HttpEntity接收数据 ### 7.1、HttpEntity:含有头和body信息 如果想同时拿到头和body的数据,可以使用,`org.springframework.http.HttpEntity`来接收数据,这个类中包含了头和body的信息,body是一个泛型,http请求的数据会被转换为body对应的T类型。 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/235/f341ebaa-1bb0-4fb3-a24c-301f9a319d35.png) ### 7.2、案例代码 > 注意:HttpEntity类型的参数不要用@RequestBody标注。 ```java @RequestMapping("/requestbody/test5") public String test5(HttpEntity<User> httpEntity) { //header信息 HttpHeaders headers = httpEntity.getHeaders(); System.out.println("headers:" + headers); //body中的内容会自动转换为HttpEntity中泛型指定的类型 User user = httpEntity.getBody(); System.out.println("body:" + user); return "ok"; } ``` ### 7.3、调用案例接口 ```java ### 发送json数据,后端用HttpEntity<User>接收 POST http://localhost:8080/chat18/requestbody/test5 Content-Type: application/json;charset=UTF-8 { "name": "路人", "age": 35, "skills": [ "高并发", "Spring", "分布式事务", "MQ", "MySQL" ] } ``` ### 7.4、控制台输出 ```properties headers:[content-type:"application/json;charset=UTF-8", content-length:"130", host:"localhost:8080", connection:"Keep-Alive", user-agent:"Apache-HttpClient/4.5.12 (Java/11.0.10)", accept-encoding:"gzip,deflate"] body:User{name='路人', age=35, skills=[高并发, Spring, 分布式事务, MQ, MySQL]} ``` **推荐阅读:**[Idea 快捷键大全.pdf](https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485664&idx=1&sn=435f9f515a8f881642820d7790ad20ce&scene=21#wechat_redirect) ## 8、案例6:使用RequestEntity接受数据 ### 8.1、RequestEntity:包含更多请求信息(头、method、url,body) RequestEntity的用法和案例5中的HttpEntity用法类似,RequestEntity继承了HttpEntity,包含了更多的信息,比`RequestEntity`多了2个http请求信息(method和url) ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/235/effb8756-d86d-47c5-95ca-b47134c0d6bf.png) ### 8.2、案例代码 ```java @RequestMapping("/requestbody/test6") public String test6(RequestEntity<User> requestEntity) { //请求方式 HttpMethod method = requestEntity.getMethod(); System.out.println("method:" + method); //请求地址 URI url = requestEntity.getUrl(); System.out.println("url:" + url); //body的类型,即RequestEntity后面尖括号中的类型 Type type = requestEntity.getType(); System.out.println("body的类型,即RequestEntity后面尖括号中的类型:" + type); //header信息 HttpHeaders headers = requestEntity.getHeaders(); System.out.println("headers:" + headers); //body中的内容会自动转换为HttpEntity中泛型指定的类型 User user = requestEntity.getBody(); System.out.println("body:" + user); return "ok"; } ``` ### 8.3、调用案例接口 ```java ### 发送json数据,后端用对象接收 POST http://localhost:8080/chat18/requestbody/test6 Content-Type: application/json;charset=UTF-8 { "name": "路人", "age": 35, "skills": [ "高并发", "Spring", "分布式事务", "MQ", "MySQL" ] } ``` ### 8.4、控制台输出 ```properties method:POST url:http://localhost:8080/chat18/requestbody/test6 body的类型,即RequestEntity后面尖括号中的类型:class com.javacode2018.springmvc.chat18.controller.RequestBodyController$User headers:[content-type:"application/json;charset=UTF-8", content-length:"130", host:"localhost:8080", connection:"Keep-Alive", user-agent:"Apache-HttpClient/4.5.12 (Java/11.0.10)", accept-encoding:"gzip,deflate"] body:User{name='路人', age=35, skills=[高并发, Spring, 分布式事务, MQ, MySQL]} ``` ## 9、@RequestBody还可以如何使用呢? 这里留给大家去研究,大家在运行一下案例1中的用例1 ```java ### 发送纯文本 POST http://localhost:8080/chat18/requestbody/test1 Content-Type: text/plain 这里是body部分,欢迎访问我的博客:itsoku.com,上面有更多系列文章 ``` 控制台有更详细的输出如下,注意里面的`RequestResponseBodyMethodProcessor`,这个就是`@ReqeustBody`类型的参数处理器,`@ReqeustBody`标注的参数的值都是有这个类来解析请求得到的,大家可以去看看这个类的代码,debug一番,就知道`@ReqeustBody`还有那些更炫的用法了。 ```java 23:17:05.595 [http-nio-8080-exec-9] DEBUG org.springframework.web.servlet.DispatcherServlet - POST "/chat18/requestbody/test1", parameters={} 23:17:05.595 [http-nio-8080-exec-9] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.javacode2018.springmvc.chat18.controller.RequestBodyController#test1(String) 23:17:05.596 [http-nio-8080-exec-9] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor - Read "text/plain;charset=UTF-8" to ["这里是body部分,欢迎访问我的博客:itsoku.com,上面有更多系列文章"] body:这里是body部分,欢迎访问我的博客:itsoku.com,上面有更多系列文章 23:17:05.597 [http-nio-8080-exec-9] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor - Using 'text/plain', given [*/*] and supported [text/plain, */*, application/json, application/*+json] 23:17:05.597 [http-nio-8080-exec-9] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor - Writing ["ok"] 23:17:05.598 [http-nio-8080-exec-9] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK ``` > 主要有5行日志,每行日志这里做一下解释 > > 第1行:接收到了请求,请求的信息(url,参数) > > 第2行:找到了能够处理请求的方法,即RequestBodyController#test1(String)方法可以处理当前请求 > > 第3行:参数解析器,@RequestBody对应的是RequestResponseBodyMethodProcessor > > 第4行:接口中System.out.println输出的内容 > > 第5行:返回值处理器,这个以后会有专题讲解 ## 10、@RequestBody原理 @RequestBody标注的参数取值是由`RequestResponseBodyMethodProcessor#resolveArgument`方法处理的,可以去看源码。 ## 11、代码位置及说明 ### 11.1、git地址 ```html https://gitee.com/javacode2018/springmvc-series ``` ### 11.2、本文案例代码结构说明 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/235/fa25422f-aa6d-4d69-a6de-7a2cfc9c30c3.png) <a style="display:none" target="_blank" href="https://mp.weixin.qq.com/s/_S1DD2JADnXvpexxaBwLLg" style="color:red; font-size:20px; font-weight:bold">继续收门徒,亲手带,月薪 4W 以下的可以来找我</a> ## 最新资料 1. <a href="https://mp.weixin.qq.com/s?__biz=MzkzOTI3Nzc0Mg==&mid=2247484964&idx=2&sn=c81bce2f26015ee0f9632ddc6c67df03&scene=21#wechat_redirect" target="_blank">尚硅谷 Java 学科全套教程(总 207.77GB)</a> 2. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484192&idx=1&sn=505f2faaa4cc911f553850667749bcbb&scene=21#wechat_redirect" target="_blank">2021 最新版 Java 微服务学习线路图 + 视频</a> 3. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484573&idx=1&sn=7f3d83892186c16c57bc0b99f03f1ffd&scene=21#wechat_redirect" target="_blank">阿里技术大佬整理的《Spring 学习笔记.pdf》</a> 4. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484544&idx=2&sn=c1dfe907cfaa5b9ae8e66fc247ccbe84&scene=21#wechat_redirect" target="_blank">阿里大佬的《MySQL 学习笔记高清.pdf》</a> 5. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485167&idx=1&sn=48d75c8e93e748235a3547f34921dfb7&scene=21#wechat_redirect" target="_blank">2021 版 java 高并发常见面试题汇总.pdf</a> 6. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485664&idx=1&sn=435f9f515a8f881642820d7790ad20ce&scene=21#wechat_redirect" target="_blank">Idea 快捷键大全.pdf</a> ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/1/2883e86e-3eff-404a-8943-0066e5e2b454.png)
#custom-toc-container