Spring RestTemplate为何必须搭配MultiValueMap?

举报
JavaEdge 发表于 2021/11/26 00:26:51 2021/11/26
【摘要】 微服务之间的大多都是使用 HTTP 通信,这自然少不了使用 HttpClient。 在不适用 Spring 前,一般使用 Apache HttpClient 和 Ok HttpClient 等,而一旦引入...

微服务之间的大多都是使用 HTTP 通信,这自然少不了使用 HttpClient。
在不适用 Spring 前,一般使用 Apache HttpClient 和 Ok HttpClient 等,而一旦引入 Spring,就有了更好选择 - RestTemplate。

接口:

想接受一个 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://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html

文章来源: javaedge.blog.csdn.net,作者:JavaEdge.,版权归原作者所有,如需转载,请联系作者。

原文链接:javaedge.blog.csdn.net/article/details/121527830

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。