restTemplate源码解析(一)构造restTemplate的Bean实例
所有文章
https://www.cnblogs.com/lay2017/p/11740855.html
正文
构造一个restTemplate的Bean实例很容易,只需这样配置
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
但我们希望更多得了解一个这个构造过程做了哪些事情。为此,我们需要去打开restTemplate这个黑盒子。
restTemplate设计
先试着从restTemplate得类图上获得一些灵感,看看spring的作者是一个什么样的设计思路吧。

我们看到,简单的几个类和接口展示了标准的抽象设计。
HttpAccessor是一个抽象类,它抽象的是一个http访问器的概念。这说明,RestTemplate具备http方式请求响应的处理能力。再看RestOperations,它是一个接口,抽象的是restful风格的操作方法,这意味着RestTemplate的操作风格将是Restful的。
http访问器和restful风格操作做了一个分离。restTemplate则是聚合了两者,既有http访问器的基础能力,又在这个基础之上构建了restful风格。设计者把Restful操作作为接口,其实从规范角度上,我们应该面向RestOperations接口使用它。但大多数人似乎都直接使用RestTemplate,我们上面的代码示例也无意识地直接面向了RestTemplate这个实现类。
restTemplate实例构造过程
接下来,我们再看看new一个RestTemplate对象做了哪些事情。
进入RestTemplate类的构造方法
private final List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
private UriTemplateHandler uriTemplateHandler;
public RestTemplate() {
// 添加HttpMessageConverterjie
this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(new StringHttpMessageConverter());
this.messageConverters.add(new ResourceHttpMessageConverter(false));
try {
this.messageConverters.add(new SourceHttpMessageConverter<>());
}
catch (Error err) {
// Ignore when no TransformerFactory implementation is available
}
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
if (romePresent) {
this.messageConverters.add(new AtomFeedHttpMessageConverter());
this.messageConverters.add(new RssChannelHttpMessageConverter());
}
if (jackson2XmlPresent) {
this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
}
else if (jaxb2Present) {
this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
}
if (jackson2Present) {
this.messageConverters.add(new MappingJackson2HttpMessageConverter());
}
else if (gsonPresent) {
this.messageConverters.add(new GsonHttpMessageConverter());
}
else if (jsonbPresent) {
this.messageConverters.add(new JsonbHttpMessageConverter());
}
if (jackson2SmilePresent) {
this.messageConverters.add(new MappingJackson2SmileHttpMessageConverter());
}
if (jackson2CborPresent) {
this.messageConverters.add(new MappingJackson2CborHttpMessageConverter());
}
// uri模板处理器
this.uriTemplateHandler = initUriTemplateHandler();
}
构造方法有点长,但只做了两件事
1)添加HttpMessageConverter的实现类,熟悉springmvc的话估计知道HttpMessageConverter。顾名思义,它就是用来转换http请求响应过程中的消息数据的。
2)初始化一个UriTemplateHandler
我们跟进initUriTemplateHandler方法,看看怎么初始化一个uri模板处理器的
private static DefaultUriBuilderFactory initUriTemplateHandler() {
DefaultUriBuilderFactory uriFactory = new DefaultUriBuilderFactory();
uriFactory.setEncodingMode(EncodingMode.URI_COMPONENT); // for backwards compatibility..
return uriFactory;
}
这里只是简单地构造了实例,并直接返回。由此可见,DefaultUriBuilderFactory应该直接或者间接实现了UriTemplateHandler
我们看看DefaultUriBuilderFactory的类图

与我们猜想的一样,DefaultUriBuilderFactory间接实现了UriTemplateHandler
RestTemplate的构造方法中就做了这两件事,我们再看看HttpAccessor
public abstract class HttpAccessor {
// ...
private ClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
// ...
}
默认创建了一个ClientHttpRequestFactory的实例,ClientHttpRequestFactory这个接口是用来创建客户端的request请求对象的,我们并没有去自定义设置它默认采用SimpleClientHttpRequestFactory这个实现类。
ClientHttpRequestFactory作为工厂模式,将会生产ClientHttpRequest。ClientHttpRequest抽象了Http请求操作,执行ClientHttpRequest将会发送请求与服务端交互。
总结
到这里,RestTemplate的实例构造过程就结束了。其实它的原理就是封装了http请求操作而已。
我们再大体过一下RestTemplate的构造过程
1)在RestTemplate构造方法中添加了多个HttpMessageConverter后续用于http请求响应的数据转换
2)在RestTemplate构造方法中初始化了一个Uri模板的处理器,后续用于处理uri相关的东西
3)HttpAccessor默认创建了一个ClientHttpRequestFactory的成员实例,后续用于创建请求对象。
不过,似乎最有学习价值的还是一开始的restTemplate的设计图。能够理解抽象类与接口的标准设计理念,兴许对面向对象分析与设计大有裨益。
restTemplate源码解析(一)构造restTemplate的Bean实例的更多相关文章
- 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例
前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...
- [Java多线程]-Thread和Runable源码解析之基本方法的运用实例
前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...
- restTemplate源码解析(目录)
restTemplate是spring实现的,基于restful风格的http请求模板.使用restTemplate可以简化请求操作的复杂性,同时规范了代码风格.本系列文章,将根据以下目录顺序,从源码 ...
- restTemplate源码解析(五)处理ClientHttpResponse响应对象
所有文章 https://www.cnblogs.com/lay2017/p/11740855.html 正文 上一篇文章中,我们执行了ClientHttpRequest与服务端进行交互.并返回了一个 ...
- restTemplate源码解析(二)restTemplate的核心逻辑
所有文章 https://www.cnblogs.com/lay2017/p/11740855.html 正文 上一篇文章中,我们构造了一个RestTemplate的Bean实例对象.本文将主要了解一 ...
- restTemplate源码解析(三)创建ClientHttpRequest请求对象
所有文章 https://www.cnblogs.com/lay2017/p/11740855.html 正文 上一篇文章中,我们大体看了一下restTemplate的核心逻辑.再回顾一下核心代码 p ...
- restTemplate源码解析(四)执行ClientHttpRequest请求对象
所有文章 https://www.cnblogs.com/lay2017/p/11740855.html 正文 上一篇文章中,我们创建了一个ClientHttpRequest的实例.本文将继续阅读Cl ...
- springcloud源码解析(目录)
springcloud是一个基于springboot的一站式企业级分布式应用开发框架.springboot为其提供了创建单一项目的便利性,springcloud组合了现有的.常用的分布式项目的解决方案 ...
- Spring AOP的实现及源码解析
在介绍AOP之前,想必很多人都听说AOP是基于动态代理和反射来实现的,那么在看AOP之前,你需要弄懂什么是动态代理和反射及它们又是如何实现的. 想了解JDK的动态代理及反射的实现和源码分析,请参见下面 ...
随机推荐
- 设备树中的interrupts属性解析
interrupts属性会有两种不同的参数: 1. 带两个参数的情形 示例: interrupt-parent = <&gpio2>; interrupts = <5 1& ...
- <JavaScript>尺寸类样式的获取
尺寸类样式的获取 offsetHeight HTMLElement.offsetHeight 是一个只读属性,它返回该元素的像素高度,高度包含该元素的垂直内边距和边框,且是一个整数.(content+ ...
- win7 安装 IIS 配置ASP 【原创】
1.安装https://jingyan.baidu.com/article/5553fa8215f7ef65a2393413.html2.测试localhost 打开测试没问题3.配置网站--添加站 ...
- Qt 自定义信号SIGNAL
emit toLine(lineQStr);connect(vcthread, SIGNAL(toLine(QString)), this, SLOT(appendText(QString)));
- List根据多个字段分组
List<ClassEntity> distinctClass = classEntities.stream().collect(Collectors.collectingAndThen( ...
- 【407】C函数中的指针
注意:如果对于函数中指针参数的对应值进行修改,当调用该函数后,实参会被修改,所以如果不想要实参被修改,需要为函数的形参定义一个 str_copy 的量,通过 strcpy() 进行将字符串复制给 st ...
- iOS-NSTimer计时器
(3) 计时器NSTimer + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget sel ...
- 【搬运】NumPy_for_Matlab_Users
搬运自:http://scipy.github.io/old-wiki/pages/NumPy_for_Matlab_Users.html. 1.Introduction MATLAB和NumPy/S ...
- c#窗体程序绘制简单心形
分析思路: 两个圆形和一个矩形如图叠加再逆时针旋转45°,就能得到一个极其简陋的心. 我们只需要将圆心放在矩形上边中点和右边中点即可. 代码如下: private void button1_Cli ...
- Swagger API文档
Swagger API文档集中化注册管理 接口文档是前后端开发对接时很重要的一个组件.手动编写接口文档既费时,又存在文档不能随代码及时更新的问题,因此产生了像swagger这样的自动生成接口文档的 ...