关于@RequestBody的一些分析
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于@RequestBody的一些分析相关的知识,希望对你有一定的参考价值。
参考技术A 最近在看基于SpringBoot的登录逻辑,项目测试时使用Postman模拟表单登录请求,发现,程序总是报415,也就是不支持的类型。网上查了一圈,猜测可能是前后端参数不匹配导致的问题。排查后发现 @RequestBody 有个坑:无法接收表单登录请求。基于SpringBoot,准备一个路径跳转Controller:
登录界面如下:
登录请求处理:
User 类以及 Result 不重要,这里就不写出来了, User 类只包含 username 和 password 属性。
登录测试:
但是,如果发送的是"application/json"的话:
通过不断debug,可以得到最后路径和方法的映射关系被保存在了 AbstractHandlerMethodMapping 的 mappingLookup 属性中,可以看到映射方法被封装成了 HandlerMethod 类
登录请求发出后会由 DispatcherServlet 类分配进行后续处理的方法:
DispatcherServlet 的 doDispatch 中的
分配处理器。不断debug,最后在 AbstractHandlerMethodMapping 类中的 getHandlerInternal 中看到了分配结果:
最后又回到了 Dispatch :
正式进入处理流程。
getHandler 方法会返回之前 getHandler 方法返回的处理器。
执行到 RequestMappingHandlerAdapter#invokeHandlerMethod 做一些准备,比如将 HandlerMethod 封装成 ServletInvocableHandlerMethod :
设置参数、返回值解析器:
调用 invokeAndHandlerMethod 进行处理:
毫无疑问, invokeForRequest 用于执行请求:
先获取并解析参数,再通过 doInvoke 方法执行Controller的自定义逻辑。
@RequestBody 的问题就在解析参数上。
接着,不断debug直到进入 HandlerMethodArgumentResolverComposite 的 getArgumentResolver ,事情逐渐明朗:
参数解析类出现了 RequestResponseBodyMethodProcessor ,而这个类正是用来处理 @RequestBody 和 @ResponseBody 注解的。
下面是 RequestResponseBodyMethodProcessor 抽象父类 AbstractMessageConverterMethodProcessor 的参数处理逻辑。
判断能否进行处理的逻辑( AbstractHttpMessageConverter ),其中 supports 方法和 canRead 方法均由具体的实现类提供:
可以看到,发送的JSON字符串可以由MappingJackson2HttpMessageConverter进行处理:
返回值的处理由 AbstractMessageConverterMethodProcessor 的 writeWithMessageConverters 进行,具体就不说了。
没啥结论,要有就是用 @RequestBody 和 @ResponseBody 的时候小心尽量避免表单提交,转而用Ajax或其他传送JSON数据的方式。
这篇文章很不错: Spring MVC源码(三) ----- @RequestBody和@ResponseBody原理解析
记录一些遇见的bug——关于Lombok的一个大坑,使用@RequestBody接收axios请求对象时,对象所有属性均为null
记录一些遇见的bug——关于Lombok的一个大坑,使用@RequestBody接收axios请求对象时,对象所有属性均为null
一、问题
使用axios在前台发送post请求时,后台使用@RequestBody注解接收NoticeAddFo对象,拿不到数据。
拿不到数据问题不大,问题是它也不报错。。。。
//添加公告
const noticeApis =
confirmAdd(addNotice)
return window.axios(
url:'/api/notice/add',
method:'post',
data:addNotice
)
export default noticeApis
二、原因
各种研究各种试,排除了各种错误可能,前台没有多一个或者少一个逗号,后台逻辑也没问题,前台代码后台代码各种方法重写了6遍,还是接收不到。
最后忽然发现:
springboot框架自带的set和get方法长这样子:
而查看编译后的字节码文件,Lombok替我生成的set和get方法长这样子:
以NoticeAddFo类的nContent属性为例:
springboot默认的方法是setnContent(),没有把属性名的首字母大写。
而Lombok利用反射,默认将所有属性的首字母大写来生成set和get方法,写出来的是setNContent()!
三、解决方案
(1) 不用Lombok。
使用idea工具的Generate一键生成的set和get方法与springboot框架的默认方法一样,首字母没有大写,就可以拿到值了。
(2)更改类属性名,不要用首字母小写第二个字母大写这样的格式。
以上是关于关于@RequestBody的一些分析的主要内容,如果未能解决你的问题,请参考以下文章
记录一些遇见的bug——关于Lombok的一个大坑,使用@RequestBody接收axios请求对象时,对象所有属性均为null
记录一些遇见的bug——关于Lombok的一个大坑,使用@RequestBody接收axios请求对象时,对象所有属性均为null