HttpEntityRequestCallback是RestTemplate的私有内部类,继承了RestTemplate私有内部类 AcceptHeaderRequestCallback,AcceptHeaderRequestCallback实现了RequestCallback接口,重写了doWithRequest方法
HttpEntity是 HTTP请求或响应实体
public void doWithRequest(ClientHttpRequest httpRequest) throws IOException {
//调用父类方法
super.doWithRequest(httpRequest);
Object requestBody = this.requestEntity.getBody();
//判断内部类中的HttpEntity是否有参数
if (requestBody == null) {
HttpHeaders httpHeaders = httpRequest.getHeaders();
HttpHeaders requestHeaders = this.requestEntity.getHeaders();
if (!requestHeaders.isEmpty()) {
//如果header不为空,将header的值赋给方法接收的参数ClientHttpRequest
requestHeaders.forEach((key, values) -> {
httpHeaders.put(key, new LinkedList(values));
});
}
//添加content长度
if (httpHeaders.getContentLength() < 0L) {
httpHeaders.setContentLength(0L);
}
} else {
Class<?> requestBodyClass = requestBody.getClass();
Type requestBodyType = this.requestEntity instanceof RequestEntity ? ((RequestEntity)this.requestEntity).getType() : requestBodyClass;
HttpHeaders httpHeadersx = httpRequest.getHeaders();
HttpHeaders requestHeadersx = this.requestEntity.getHeaders();
MediaType requestContentType = requestHeadersx.getContentType();
//消息转换器列表
Iterator var8 = RestTemplate.this.getMessageConverters().iterator();
while(var8.hasNext()) {
//策略接口,指定可以从HTTP请求和响应转换的转换器
HttpMessageConverter<?> messageConverter = (HttpMessageConverter)var8.next();
if (messageConverter instanceof GenericHttpMessageConverter) {
//可以将HTTP请求转换为指定泛型类型的目标对象,将指定泛型类型的源对象转换为HTTP响应
GenericHttpMessageConverter<Object> genericConverter = (GenericHttpMessageConverter)messageConverter;
//判断 指示此转换器是否可以写入给定的类
if (genericConverter.canWrite((Type)requestBodyType, requestBodyClass, requestContentType)) {
if (!requestHeadersx.isEmpty()) {
requestHeadersx.forEach((key, values) -> {
httpHeadersx.put(key, new LinkedList(values));
});
}
//打印debug日志
this.logBody(requestBody, requestContentType, genericConverter);
将给定对象写入给定的输出消息
genericConverter.write(requestBody, (Type)requestBodyType, requestContentType, httpRequest);
return;
}
} else if (messageConverter.canWrite(requestBodyClass, requestContentType)) {
if (!requestHeadersx.isEmpty()) {
requestHeadersx.forEach((key, values) -> {
httpHeadersx.put(key, new LinkedList(values));
});
}
this.logBody(requestBody, requestContentType, messageConverter);
messageConverter.write(requestBody, requestContentType, httpRequest);
return;
}
}
String message = "No HttpMessageConverter for [" + requestBodyClass.getName() + "]";
if (requestContentType != null) {
message = message + " and content type [" + requestContentType + "]";
}
throw new RestClientException(message);
}
}
private void logBody(Object body, @Nullable MediaType mediaType, HttpMessageConverter<?> converter) {
if (RestTemplate.this.logger.isDebugEnabled()) {
if (mediaType != null) {
RestTemplate.this.logger.debug("Writing [" + body + "] as \"" + mediaType + "\"");
} else {
String classname = converter.getClass().getName();
RestTemplate.this.logger.debug("Writing [" + body + "] with " + classname);
}
}
}
响应提取器,它使用给定的实体转换器 将响应转换为类型T
最后的execute方法
@Nullable
public <T> T execute(String url, HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor, Object... uriVariables) throws RestClientException {
//使用URI变量映射展开给定的URI模板
URI expanded = this.getUriTemplateHandler().expand(url, uriVariables);
return this.doExecute(expanded, method, requestCallback, responseExtractor);
}
参数:url - 要连接的完全扩展的URL, method - 要执行的HTTP方法(GET,POST等), requestCallback- 准备请求的对象(可以null), responseExtractor- 从响应中提取返回值的对象(可以null)
@Nullable
protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {
Assert.notNull(url, "URI is required");
Assert.notNull(method, "HttpMethod is required");
ClientHttpResponse response = null;
Object var14;
try {
//通过工厂模式创建ClientHttpRequest对象
ClientHttpRequest request = this.createRequest(url, method);
if (requestCallback != null) {
requestCallback.doWithRequest(request);
}
//执行请求
response = request.execute();
//处理给定的响应,执行适当的日志记录并在ResponseErrorHandler必要时调用
this.handleResponse(url, method, response);
//extractData 从给定数据中提取数据ClientHttpResponse并将其返回
var14 = responseExtractor != null ? responseExtractor.extractData(response) : null;
} catch (IOException var12) {
String resource = url.toString();
String query = url.getRawQuery();
resource = query != null ? resource.substring(0, resource.indexOf(63)) : resource;
throw new ResourceAccessException("I/O error on " + method.name() + " request for \"" + resource + "\": " + var12.getMessage(), var12);
} finally {
if (response != null) {
response.close();
}
}
return var14;
}
- restTemplate源码解析(五)处理ClientHttpResponse响应对象
所有文章 https://www.cnblogs.com/lay2017/p/11740855.html 正文 上一篇文章中,我们执行了ClientHttpRequest与服务端进行交互.并返回了一个 ...
- RestTemplate post请求使用map传参 Controller 接收不到值的解决方案 postForObject方法源码解析.md
结论 post方法中如果使用map传参,需要使用MultiValueMap来传递 RestTemplate 的 postForObject 方法有四个参数 String url => 顾名思义 ...
- RestTemplate post请求 Controller 接收不到值的解决方案 postForObject方法源码解析
springboot 整合 RestTemplate 与 使用方法 RestTemplate 的 postForObject 方法有四个参数 String url => 顾名思义 这个参数是请求 ...
- 【Spring-web】RestTemplate源码学习
2016-12-22 by 安静的下雪天 http://www.cnblogs.com/quiet-snowy-day/p/6210288.html 前言 在Web开发工作中,有一部分开发任务 ...
- restTemplate源码解析(目录)
restTemplate是spring实现的,基于restful风格的http请求模板.使用restTemplate可以简化请求操作的复杂性,同时规范了代码风格.本系列文章,将根据以下目录顺序,从源码 ...
- restTemplate源码详解深入剖析底层实现思路
一 准备工作 1 启动一个项目,发布一个restful的get请求,端口设置为8090. @RestController @RequestMapping("/youku1327") ...
- Ribbon源码分析(一)-- RestTemplate 以及自定义负载均衡算法
如果只是想看ribbon的自定义负载均衡配置,请查看: https://www.cnblogs.com/yangxiaohui227/p/13186004.html 注意: 1.RestTemplat ...
- RestTemplate Hashmap变为LinkedHashMap源码解读
使用restTemplate远程调用服务,正常应该接收List<HashMap>数据,但实际却是List<LikedHashMap>经过不断地debug,终于找到了数据被转换成 ...
- restTemplate.postForObject上传文件中文乱码(???.xls)
一.问题描述 项目中, 使用restTemplate上传文件时, 文件名中文乱码, 一串问号, 源文件名为: 测试中文乱码哦哦哦.zip, 通过restTemplate.postForObject调用 ...
- spring cloud深入学习(四)-----eureka源码解析、ribbon解析、声明式调用feign
基本概念 1.Registe 一一服务注册当eureka Client向Eureka Server注册时,Eureka Client提供自身的元数据,比如IP地址.端口.运行状况指标的Uri.主页地址 ...
随机推荐
- 【199】ArcGIS 添加自定义工具到工具箱
点击工具栏最右边的三角块,弹出菜单,点击“Customize”. 切换到“Command”,在搜索框中输入“idw”查找相应工具,然后将工具通过鼠标左键拖拽到工具栏中. 在工具上右键修改工具的显示图片 ...
- 骨骼蒙皮动画(Skinned Mesh)的原理解析(二)
http://blog.csdn.net/jimoshuicao/article/details/9283071 2)蒙皮信息和蒙皮过程 2-1)Skin info的定义 上文曾讨论过,Skinned ...
- React的深入浅出
react组件重新渲染有两种途径:1.自身调用setState:2.父组件传入新的props.3.但这两种途径都不会必然调用render而引起重新渲染, 都会先经过shouldComponentUpd ...
- IO流案例:1.复制多级文件夹 2.删除多级文件夹
package copy; /* 需求:复制多级文件夹 复制d:\\itcast(包含文件和子文件夹)到模块目录下 分析: d:\\itcast a.txt b.txt javaweb a.xml b ...
- 远程报:这可能是由于credssp加密oracle修正
此错误解决办法 1.Win+R 输入regedit打开注册表 找到对应的以下目录HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion ...
- Magic Numbers CodeForces - 628D
Magic Numbers CodeForces - 628D dp函数中:pos表示当前处理到从前向后的第i位(从1开始编号),remain表示处理到当前位为止共产生了除以m的余数remain. 不 ...
- JAVA常用知识总结(二)
JAVA中的参数传递总结先看两道笔试题: public class Test2 { public static void main (String [] args) { StringBuffer a ...
- 1536 不一样的猜数游戏 dp思维 + 找规律
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1536 首先,要知道值为n的答案,则可以这么去想,知道值为n - 1的答案 ...
- SonarQube+Svn+Jenkins环境搭建----问题总结
1.配置SVN后提示unable to access to repository,原因是使用的账户没有访问svn的权限,创建新的用户即可.注意新的用户,用户名,密码要跟svn上的权限一致. 创 ...
- 小程序java解密
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk16< ...