文章结构
- 问题背景:
- 问题处理
- 总结
问题背景:
现有如下代码:
@PostMapping(value = "/payment/create")
@ResponseBody
public CommonResult create(Payment payment) {}
乍眼看去是不是很好,至少没啥问题很自然,像大自然一样自然,但是确实是有问题的
问题现象:通过 postman 发送 post 请求,payment 能收到参数;而通过分布式远程调用却接收不到参数,这是为什么呢
问题处理
思路:先看看参数有没有发送过来,其次看看是不是处理参数失败了
1、首先在 DispatcherServlet
类的 doDispatch
方法上打了一个断点,用 Idea 的 debug 窗口执行如下命令:
// 查看 post 请求中 body 数据的
new String(((Http11InputBuffer) ((RequestFacade) request).request.coyoteRequest.inputBuffer).byteBuffer.hb)
很简单读者自行操作一下:查看请求 body 的数据,确认下请求中有没有携带参数
通过查看 http 请求的 body,发现参数数据是有的,也就是说参数有但没有解析到变量 payment 中。问题自然出现在参数解析器上面。继续
2、调查发现postman发送的请求类型是 multipart/form-data
类型,也就是表单提交类型,这种类型一般发生在前端直接提交请求到后台,而分布式调用一般是 contextType=application/json
类型
背景知识:参数解析器(HandlerMethodArgumentResolver)是有顺序的,不同的参数解析器能解析的参数不一样
3、到这里问题大致是定位到了,需要设置正确的contentType类型,接下来就是验证流程
代码写的不对,我们代码针对的是表单形式的 contentType 而分布式环境下发送的是 JSON 形式的 contentType
4、修改代码如下:添加 @RequestBody
注解!!!
@PostMapping(value = "/payment/create")
@ResponseBody
public CommonResult create(@RequestBody Payment payment) {}
5、参数 payment 成功接收到请求数据
总结
总结:分布式环境下,默认都把 @RequestBody
和 @ResponseBody
注解加上,不给自己找麻烦!!!
传送门: 保姆式Spring5源码解析
欢迎与作者一起交流技术和工作生活
联系作者