RestTemplate post请求使用map传参 Controller 接收不到值的解决方案 postForObject方法源码解析.md

时间:2021-01-21 04:16:24

结论

post方法中如果使用map传参,需要使用MultiValueMap来传递

RestTemplate 的 postForObject 方法有四个参数

  • String url => 顾名思义 这个参数是请求的url路径

  • Object request => 请求的body 这个参数需要再controller类用 @RequestBody 注解接收

  • Class responseType => 接收响应体的类型

  • 第四个参数 postForObject 方法多种重构

    Map<String,?> uriVariables => uri 变量 顾名思义 这是放置变量的地方

    Object... uriVariables => 可变长 Object 类型 参数

@Nullable
public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor(responseType, this.getMessageConverters(), this.logger);
return this.execute(url, HttpMethod.POST, requestCallback, responseExtractor, (Object[])uriVariables);
} @Nullable
public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException {
RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor(responseType, this.getMessageConverters(), this.logger);
return this.execute(url, HttpMethod.POST, requestCallback, responseExtractor, (Map)uriVariables);
} @Nullable
public <T> T postForObject(URI url, @Nullable Object request, Class<T> responseType) throws RestClientException {
RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor(responseType, this.getMessageConverters());
return this.execute(url, HttpMethod.POST, requestCallback, responseExtractor);
}

首先我们使用最简单的一种 可变长Object 参数 进行传值

@Service
public class HelloService { @Autowired
RestTemplate restTemplate; public String helloService(String name,Integer age){
return restTemplate.postForObject("http://SERVICE-HELLO/hello?name={name}&age={age}", null, String.class, name,age);
}
}

需要再url上拼接参数并使用{参数名}占位符站位

然后将参数放到 第四个参数 可变长 Object 参数上 即可

Controller类代码

@RestController
public class DemoController {
@Value("${server.port}")
String port; @PostMapping("hello")
public String home(String name,Integer age){
return "hello " + name + " you age is " + age + " ,i am from port:" + port;
}
}

测试成功

接下来我们使用 Map传值

map传值也很简单

public String helloService(String name,Integer age){
Map<String,Object> map = new HashMap<>();
map.put("name",name);
map.put("age",age);
return restTemplate.postForObject("http://SERVICE-HELLO/hello?name={name}&age={age}", null, String.class, map);
}

只需要将参数放入到map中即可

那有些人要问了 , 为什么不能用 第二个 request 参数传值 , 其实是可以的

我试过用HashMap 和 LinkedHashMap 都是接收不到的

所以我们来看一下源码是怎么写的

首先进入到 postForObject 方法中 发现request 参数 传入了一个 httpEntityCallBack 方法中 , 那么接着追踪

@Nullable
public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException {
RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor(responseType, this.getMessageConverters(), this.logger);
return this.execute(url, HttpMethod.POST, requestCallback, responseExtractor, (Map)uriVariables);
}

进入httpEntityCallBack方法中

httpEntityCallBack方法又调用了 RestTemplate的HttpEntityRequestCallback方法

public <T> RequestCallback httpEntityCallback(@Nullable Object requestBody, Type responseType) {
return new RestTemplate.HttpEntityRequestCallback(requestBody, responseType);
}

进入HttpEntityRequestCallback

这里会出现一个分支 instanceof 类型判定 requestBody 参数是否是 HttpEntity类型

public HttpEntityRequestCallback(@Nullable Object requestBody, @Nullable Type responseType) {
super(responseType);
if (requestBody instanceof HttpEntity) {
this.requestEntity = (HttpEntity)requestBody;
} else if (requestBody != null) {
this.requestEntity = new HttpEntity(requestBody);
} else {
this.requestEntity = HttpEntity.EMPTY;
} }

如果不是则 创建一个HttpEntity类将 requestBody 参数传入

那么我们来看一下 HttpEntity 是怎么个构造

public HttpEntity(T body) {
this(body, (MultiValueMap)null);
} public HttpEntity(MultiValueMap<String, String> headers) {
this((Object)null, headers);
}

这里可以看到 HttpEntity 有两个构造方法 一个是 传入 泛型的body 另一个是传入 MultiValueMap<String,String> headers

那么 这个MultiValueMap 是个什么东东

百度一下 发现

MultiValueMap 可以让一个key对应多个value,感觉是value产生了链表结构,可以很好的解决一些不好处理的字符串问题

那么我们来用这个奇怪的map实验一下

首先进入 MultiValueMap 接口 找到他的实现类

实现类到idea中查找

MultiValueMap 的实现类应该是 LinkedMultiValueMap

那么我们走起

public String helloService(String name,Integer age){
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
paramMap.add("name",name);
paramMap.add("age", age);
return restTemplate.postForObject("http://SERVICE-HELLO/hello",paramMap,String.class);
}

controller代码

public class DemoController {

    @Value("${server.port}")
String port; @PostMapping("hello")
public String home(String name,Integer age){
return "MultiValueMap : hello " + name + " you age is " + age + " ,i am from port:" + port;
}
}

测试成功

参考

原文:https://blog.csdn.net/weixin_40461281/article/details/83472648

RestTemplate post请求使用map传参 Controller 接收不到值的解决方案 postForObject方法源码解析.md的更多相关文章

  1. RestTemplate post请求 Controller 接收不到值的解决方案 postForObject方法源码解析

    springboot 整合 RestTemplate 与 使用方法 RestTemplate 的 postForObject 方法有四个参数 String url => 顾名思义 这个参数是请求 ...

  2. restTemplate getForObject中map传参问题

    在使用restTemplate中getForObject的map传参形式时: 开始时我是这么调用的: RestTemplate rest = new RestTemplate(); Map<St ...

  3. jmeter运行脚本后,请求偶发性的传参错误

    问题现象:jmeter写好脚本后,请求偶发性的传参错误 排查过程:1.结合报错返回值,看是不是线程并发引起: 2.排除线程并发引起后,看看是不是取值策略:如果是参数化,看看是不是每次迭代,每次都取唯一 ...

  4. asp&period;net Get和Post传参和接收参数

    asp.netGet和Post传参和接收参数 Get请求: 对于传参:test.aspx?name=%e5%bc%a0%e4%b8%89 接收参数的方法: Request.QueryString[&q ...

  5. 在ListBoxItem的样式中的button传参&comma;把当前选中项传递到命令的方法

    原文:在ListBoxItem的样式中的button传参,把当前选中项传递到命令的方法 前端页面: <Style x:Key="ThumbItemStyle" TargetT ...

  6. iOS网络请求-AFNetworking源码解析

    趁着端午节日,自己没有什么过多的安排,准备花4-5天左右,针对网络请求源码AFNetworking和YTKNetwork进行解析以及这两年多iOS实际开发经验(其实YTKNetwork也是对AFNet ...

  7. &num; Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析&num;

    Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析 Volley源码一共40多个类和接口.除去一些工具类的实现,核心代码只有20多个类.所以相对来说分析起来没有那么吃力.但是要想分析透 ...

  8. ReactiveCocoa源码解析&lpar;五&rpar; SignalProtocol的observe&lpar;&rpar;、Map、Filter延展实现

    上篇博客我们对Signal的基本实现以及Signal的面向协议扩展进行了介绍, 详细内容请移步于<Signal中的静态属性静态方法以及面向协议扩展>.并且聊了Signal的所有的g功能扩展 ...

  9. 【安卓网络请求开源框架Volley源码解析系列】定制自己的Request请求及Volley框架源码剖析

    通过前面的学习我们已经掌握了Volley的基本用法,没看过的建议大家先去阅读我的博文[安卓网络请求开源框架Volley源码解析系列]初识Volley及其基本用法.如StringRequest用来请求一 ...

随机推荐

  1. 新型序列化类库MessagePack,比JSON更快、更小的格式

    MessagePack is an efficient binary serialization format. It lets you exchange data among multiple la ...

  2. 850 USB 烧录模式

    /************************************************************************* * 850 USB 烧录模式 * 说明: * 本文 ...

  3. Bootstrap基础学习&lpar;一&rpar;&mdash&semi;表格与按钮

    一.Bootstrap 概述      Bootstrap 是由 Twitter 公司(全球最大的微博)的两名技术工程师研发的一个基于HTML.CSS.JavaScript 的开源框架.该框架代码简洁 ...

  4. x264源代码简单分析:编码器主*分-2

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  5. Java破解图片防盗链

    前言 今天想下载几张好看的壁纸,然后发现了一张是自己比较喜欢的额.然后点进去看看,WOW!好多好看的壁纸呀,于是我就起了贪念.哈哈!想把他们这一组图片打包下载,小白的方法就是一张一张下载,那样对于我们 ...

  6. H5外包团队&colon;使用HTML5播放短视频代码分享

    滑动代码 /** * 滑动处理 */ function Touch() { this.init(); } Touch.fn = Touch.prototype; Touch.fn.init = fun ...

  7. Cocostudio 1&period;4 实现的Demo程序源码

    开发环境是CocoStudio 1.4 + Cocos2dx 2.2.3  把项目文件放到Cocos2dx下的projects文件夹下就可以执行了 压缩包里面包括了 源码 和资源文件 1.DemoSh ...

  8. python列表和字符串的三种逆序遍历方式

    python列表和字符串的三种逆序遍历方式 列表的逆序遍历 a = [1,3,6,8,9] print("通过下标逆序遍历1:") for i in a[::-1]: print( ...

  9. 在虚拟机安装windows xp时所需要的序列号

    最新的windows xp sp3序列号 xp序列号 最新的windows xp sp3序列号(绝对可通过正版验证)  MRX3F-47B9T-2487J-KWKMF-RPWBY(工行版) 可用(强推 ...

  10. netstat-ll-grep-nohup-df-supervisord

    ============http://man.linuxde.net/=========== 0 vi / n是查找下一个,alt+n是上一个  u撤销上一步,回到上一步 1. 根据进程号(4974) ...