Spring RestTemplate为何必须搭配MultiValueMap?
想接受一个 Form 表单请求,读取表单定义的两个参数 para1 和 para2,然后作为响应返回给客户端。
定义完接口后,使用 RestTemplate 来发送一个这样的表单请求,代码示例如下:
上述代码定义了一个 Map,包含了 2 个表单参数,然后使用 RestTemplate 的 postForObject 提交这个表单。 执行代码提示 400 错误,即请求出错:
就是缺少 para1 表单参数,why?
解析
RestTemplate 提交的表单,最后提交请求啥样? Wireshark 抓包:
实际上是将定义的表单数据以 JSON 提交过去了,所以我们的接口处理自然取不到任何表单参数。 why?怎么变成 JSON 请求体提交数据呢?注意 RestTemplate 执行调用栈:
最终使用的 Jackson 工具序列化了表单
用到 JSON 的关键原因在
RestTemplate.HttpEntityRequestCallback#doWithRequest
根据当前要提交的 Body 内容,遍历当前支持的所有编解码器:
- 若找到合适编解码器,用之完成 Body 转化
看下 JSON 的编解码器对是否合适的判断
AbstractJackson2HttpMessageConverter#canWrite
可见,当使用的 Body 为 HashMap,是可完成 JSON 序列化的。 所以后续将这个表单序列化为请求 Body了。
但我还是疑问,为何适应表单处理的编解码器不行? 那就该看编解码器判断是否支持的实现:
FormHttpMessageConverter#canWrite
可见只有当我们发送的 Body 是 MultiValueMap 才能使用表单来提交。 原来使用 RestTemplate 提交表单必须是 MultiValueMap! 而我们案例定义的就是普通的 HashMap,最终是按请求 Body 的方式发送出去的。
修正
换成 MultiValueMap 类型存储表单数据即可:
修正后,表单数据最终使用下面的代码进行了编码:
FormHttpMessageConverter#write
发送出的数据截图如下:
这就对了!其实官方文档也说明了:
链接:https://juejin.cn/post/7035246763069947918
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
2021-04-27 C#调用DLL的几种方法
2019-04-27 Groovy Closure简介
2019-04-27 一次搞懂----模块化、组件化、插件化和热修复