所有文章

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实例的更多相关文章

  1. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  2. [Java多线程]-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  3. restTemplate源码解析(目录)

    restTemplate是spring实现的,基于restful风格的http请求模板.使用restTemplate可以简化请求操作的复杂性,同时规范了代码风格.本系列文章,将根据以下目录顺序,从源码 ...

  4. restTemplate源码解析(五)处理ClientHttpResponse响应对象

    所有文章 https://www.cnblogs.com/lay2017/p/11740855.html 正文 上一篇文章中,我们执行了ClientHttpRequest与服务端进行交互.并返回了一个 ...

  5. restTemplate源码解析(二)restTemplate的核心逻辑

    所有文章 https://www.cnblogs.com/lay2017/p/11740855.html 正文 上一篇文章中,我们构造了一个RestTemplate的Bean实例对象.本文将主要了解一 ...

  6. restTemplate源码解析(三)创建ClientHttpRequest请求对象

    所有文章 https://www.cnblogs.com/lay2017/p/11740855.html 正文 上一篇文章中,我们大体看了一下restTemplate的核心逻辑.再回顾一下核心代码 p ...

  7. restTemplate源码解析(四)执行ClientHttpRequest请求对象

    所有文章 https://www.cnblogs.com/lay2017/p/11740855.html 正文 上一篇文章中,我们创建了一个ClientHttpRequest的实例.本文将继续阅读Cl ...

  8. springcloud源码解析(目录)

    springcloud是一个基于springboot的一站式企业级分布式应用开发框架.springboot为其提供了创建单一项目的便利性,springcloud组合了现有的.常用的分布式项目的解决方案 ...

  9. Spring AOP的实现及源码解析

    在介绍AOP之前,想必很多人都听说AOP是基于动态代理和反射来实现的,那么在看AOP之前,你需要弄懂什么是动态代理和反射及它们又是如何实现的. 想了解JDK的动态代理及反射的实现和源码分析,请参见下面 ...

随机推荐

  1. 设备树中的interrupts属性解析

    interrupts属性会有两种不同的参数: 1. 带两个参数的情形 示例:  interrupt-parent = <&gpio2>; interrupts = <5 1& ...

  2. <JavaScript>尺寸类样式的获取

    尺寸类样式的获取 offsetHeight HTMLElement.offsetHeight 是一个只读属性,它返回该元素的像素高度,高度包含该元素的垂直内边距和边框,且是一个整数.(content+ ...

  3. win7 安装 IIS 配置ASP 【原创】

    1.安装https://jingyan.baidu.com/article/5553fa8215f7ef65a2393413.html2.测试localhost  打开测试没问题3.配置网站--添加站 ...

  4. Qt 自定义信号SIGNAL

    emit toLine(lineQStr);connect(vcthread, SIGNAL(toLine(QString)), this, SLOT(appendText(QString)));

  5. List根据多个字段分组

    List<ClassEntity> distinctClass = classEntities.stream().collect(Collectors.collectingAndThen( ...

  6. 【407】C函数中的指针

    注意:如果对于函数中指针参数的对应值进行修改,当调用该函数后,实参会被修改,所以如果不想要实参被修改,需要为函数的形参定义一个 str_copy 的量,通过 strcpy() 进行将字符串复制给 st ...

  7. iOS-NSTimer计时器

    (3) 计时器NSTimer + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget sel ...

  8. 【搬运】NumPy_for_Matlab_Users

    搬运自:http://scipy.github.io/old-wiki/pages/NumPy_for_Matlab_Users.html. 1.Introduction MATLAB和NumPy/S ...

  9. c#窗体程序绘制简单心形

    分析思路: 两个圆形和一个矩形如图叠加再逆时针旋转45°,就能得到一个极其简陋的心. 我们只需要将圆心放在矩形上边中点和右边中点即可. 代码如下:   private void button1_Cli ...

  10. Swagger API文档

    Swagger API文档集中化注册管理   接口文档是前后端开发对接时很重要的一个组件.手动编写接口文档既费时,又存在文档不能随代码及时更新的问题,因此产生了像swagger这样的自动生成接口文档的 ...