结论

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.net Get和Post传参和接收参数

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

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

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

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

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

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

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

  8. ReactiveCocoa源码解析(五) SignalProtocol的observe()、Map、Filter延展实现

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

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

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

随机推荐

  1. python开发基础作业02:三级菜单,使用字典dic及列表

    作业要求及提示:三级菜单 ''' 1.三级菜单 2.可依次进入各子菜单 3.菜单能够回到上一级 4.用到知识点:字典.列表.多层循环.函数 条件:基本  if  else 嵌套  if...if... ...

  2. configure: error: no acceptable C compiler found in $PATH 解决

    在安装keepalived时报错 ./configure --prefix=/usr/local/ccbase/keepalived-2.0.15 && make && ...

  3. bugku 本地包含

    本地包含 题目信息 地址:http://123.206.87.240:8003/ <?php include "flag.php"; $a = @$_REQUEST['hel ...

  4. 微信小程序中showToast 提示

    icon可以none,也可以 success wx.showToast({ title: '已提交', icon: 'success', duration: 2000 })

  5. 【SSH】spring 整合 hibernate

    spring-hibernate-1.2.9.jar applicationContext.xml <bean id="sessionFactory" class=" ...

  6. 每天进步一点点------Sobel算子(2)

    转载  http://blog.csdn.net/tianhai110 索贝尔算子(Sobel operator)主要用作边缘检测,在技术上,它是一离散性差分算子,用来运算图像亮度函数的灰度之近似值. ...

  7. 解决:执行python脚本,提示错误:/usr/bin/python^M: 解释器错误: 没有那个文件或目录。

    执行python脚本,提示错误: /usr/bin/python^M: 解释器错误: 没有那个文件或目录. 产生错误原因: \r字符被显示为^M,这时候只需要删除这个字符就可以了. Linux环境下: ...

  8. Hadoop架构: 关于Recovery (Lease Recovery , Block Recovery, PipeLine Recovery)

    该系列总览: Hadoop3.1.1架构体系——设计原理阐述与Client源码图文详解 : 总览 在HDFS中,有三种Recovery 1.Lease Recovery 2.Block Recover ...

  9. 《爬虫学习》(一)(HTTP协议)

    Http请求: 1.在浏览器中发送一个http请求的过程: 2.url详解: URL是Uniform Resource Locator的简写,统一资源定位符. 一个URL由以下几部分组成 scheme ...

  10. 你知道for(;;) vs. while(true)那个更快吗?

    来来来, for(;;) vs. while(true) 有什么区别?从java的语义上来说,他们是一模一样的.为何怎么说? 开始我们先测试for(;;) package com.tony.test; ...