2016-12-28 by 安静的下雪天  http://www.cnblogs.com/quiet-snowy-day/p/6228198.html 

本篇概要

RestTemplate类图

RestTemplate 类中省略了静态成员变量、变量的set/get方法以及实现的接口方法,

RestOperations 接口中省略了参数类型及重载的方法。这样既可以保证各个要素尽量在一幅图中展现,又不会影响理解。

返回顶部

postForEntity 处理过程

以postForEntity方法作为切入点,来梳理一下请求是如何执行的,以下概要流程图。(灰色方框内为doExcute方法的内部处理。)

postForEntity方法中,创建了两个内部类对象requestCallback和responseExtractor并传递给execute方法,分别用于请求和响应的关键处理。
总结了一下,不管是请求还是响应,这里的关键处理就是明确资源的媒体类型(也就是要明确请求端和响应端交换的信息的格式),
根据媒体类型选择适合的解析器,将消息写入输出流或者从输入流读入。

返回顶部

requestCallback.doWithRequest 处理过程

——内部类AcceptHeaderRequestCallback.doWithRequest的处理。
发送请求时,Http头部需要设置Accept字段,该字段表明了发送请求的这方接受的媒体类型(消息格式),也是响应端要返回的信息的媒体类型(消息格式)。
根据postForEntity方法的第三个参数responseType,程序将选择适合的解析器XXXConverter,并依据该解析器找出所有支持的媒体类型。
 
 ——内部类HttpEntityRequestCallback.doWithRequest的处理。
如果是POST请求并且消息体存在时,除了设置Accept字段,还可能需要设置Content-Type字段,该字段表明了所发送请求的媒体类型(消息格式),也是响应端接受的媒体类型(消息格式)。
根据postForEntity方法的第二个参数request,程序将选择适合的解析器XXXConverter,将请求消息写入输出流。
返回顶部

responseExtractor.extractData 处理过程

与请求消息体的处理过程相似。

虽然,postForEntity方法中responseExtractor对象的类型为ResponseEntityResponseExtractor,但是实际执行处理过程是HttpMessageConverterExtractor的对象实例。
在postForObject方法中,则是直接使用了HttpMessageConverterExtractor创建对象。

下图画出的也是HttpMessageConverterExtractor类中的extractData方法的处理过程。

返回顶部

关于GenericHttpMessageConverter

在以上几个方法的梳理过程中,我注意到每次消息解析转换都要作GenericHttpMessageConverter分支判断,为什么呢?

GenericHttpMessageConverter接口继承自HttpMessageConverter接口,二者都是在org.springframework.http.converter路径下。
此包中还有其他几种Converter实现类,看名字就可以猜到主要功能。唯独GenericHttpMessageConverter没猜出来。
于是,我在eclipse中使用Ctrl+Shift+G快捷键搜索了一下它的实现类AbstractGenericHttpMessageConverter。
看到AbstractJackson2HttpMessageConverter类的时候,我好像明白了。
GenericHttpMessageConverter是其他转换器派生类的接口,用于解析特殊格式的资源,比如json,xml等。
返回顶部

关于RestTemplate 中的转换器列表

转换器列表messageConverters是final类型的,由RestTemplate的构造函数赋值。一旦创建了RestTemplate对象,该对象也就同时拥有了一个当前系统支持的转换器列表。
 
那么,对于需要引用jar包的转换器,RestTemplate是怎么添加转换器实例的呢?
在声明messageConverters列表之前,定义了几个布尔型静态常量,该常量是对某一个特殊类是否可以被加载的判断结果。
在RestTemplate的构造函数中,根据该常量值来判断是否将某个转换器的实例加入到列表中。
 
由此可知,RestTemplate的初始化顺序:
创建(new)一个RestTemplate实例时,首先装载RestTemplate类,然后按照出现的顺序转载静态变量或代码。
装载完成之后,进行实例化。首先实例化成员变量,然后执行构造函数。
 
那么,外部引用的类是否可以被加载具体是怎么判断的?
通过ClassUtils.isPresent(String className, ClassLoader classLoader)方法。——感觉ClassUtils可以单独写一篇orz
ClassUtils 类在 spring-core 工程的 org.springframework.util 路径下。
简单来说,isPresent实际上是返回了ClassUtils.forName方法的处理结果,当forName方法正常执行,则鉴定的类被加载,返回true;若抛出异常(注意,此处异常是Throwable)则返回false。
forName方法的处理是:
首先,根据类名的长度(<=8)来确定是否是原始类型,若是原始类型则返回类对象Class<?>。
其次,判断是否是普通类型,若是原始类型则返回类对象Class<?>。
第三,判断是否数组类型,通过过滤"["字符截取类名,递归调用forName方法获取类对象,然后利用反射Array.newInstance创建对象并返回。
最后,排除以上情况后,使用classLoader来加载className指定的类。
 

补充

原始类型:Java的基本类型及其包装类,基本类型的数组类对象,以及空类型void.class。
 
普通类型:
 

返回顶部

转载 关于restTemplate 内部实现的更多相关文章

  1. 转载->CPU的内部架构和工作原理

    CPU的内部架构和工作原理 本片博客转自:http://www.cnblogs.com/onepixel/p/8724526.html  感谢博主分享! 内部架构 CPU 的根本任务就是执行指令,对计 ...

  2. (转载)spring RestTemplate用法详解

    前面介绍过spring的MVC结合不同的view显示不同的数据,如:结合json的view显示json.结合xml的view显示xml文档.那么这些数据除了在WebBrowser中用JavaScrip ...

  3. [转载] 淘宝内部分享:怎么跳出MySQL的10个大坑(上)

    原文: http://mp.weixin.qq.com/s?__biz=MzAxNjAzMTQyMA==&mid=209773318&idx=1&sn=e9600d3db80b ...

  4. 转载: 华为内部Web安全测试原则

    原链接:http://www.ha97.com/5520.html Web安全原则 1.认证模块必须采用防暴力破解机制,例如:验证码或者多次连续尝试登录失败后锁定帐号或IP. 说明:如采用多次连续尝试 ...

  5. Spring Boot使用RestTemplate消费REST服务的几个问题记录

    我们可以通过Spring Boot快速开发REST接口,同时也可能需要在实现接口的过程中,通过Spring Boot调用内外部REST接口完成业务逻辑. 在Spring Boot中,调用REST Ap ...

  6. SpringBoot26 RestTemplate、WebClient

    1 RestTemplate RestTemplate是在客户端访问 Restful 服务的一个核心类:RestTemplate通过提供回调方法和允许配置信息转换器来实现个性化定制RestTempla ...

  7. RestTemplate使用不当引发的问题分析

    背景 系统: SpringBoot开发的Web应用: ORM: JPA(Hibernate) 接口功能简述: 根据实体类ID到数据库中查询实体信息,然后使用RestTemplate调用外部系统接口获取 ...

  8. RestTemplate 使用中的几个问题

    Spring Boot使用RestTemplate消费REST服务的几个问题记录 我们可以通过Spring Boot快速开发REST接口,同时也可能需要在实现接口的过程中,通过Spring Boot调 ...

  9. MySQL -- 内部临时表

    本文转载自MySQL -- 内部临时表 UNION UNION语义:取两个子查询结果的并集,重复的行只保留一行 表初始化 CREATE TABLE t1(id INT PRIMARY KEY, a I ...

随机推荐

  1. 谈谈刚接触sea.js框架得看法

    向大神致敬,也是我接触框架得开始. 感谢张鑫旭大神,专业!致敬~   sea.js的7个API,都在下面得链接中有详细说明: http://www.zhangxinxu.com/sp/seajs/do ...

  2. 部署到VM的虚拟机提示“未连接到网络”

    以下可以看到网络图标为叉叉

  3. Informatica存储库和集成服务的配置

    1.配置存储库 首先登陆informatica的管理界面: 这里的用户名不区分大小写(注意后面配置集成服务是区分的,后面会提到)

  4. 两个Fragment之间传递数据

    1.第一个Fragment BlankFragment blankFragment = new BlankFragment();Bundle bundle = new Bundle();bundle. ...

  5. 解决Eclipse中新创建的Maven项目不自动创建web.xml文件

    1. 通过J2EE tools 2.项目右键-properties-project facets-勾选dynamic web moudle

  6. Windows下MySQL多实例运行

    1.正常安装Windows版的MySQL,例如安装在C:\Program Files\MySQL文件夹里: 2.按照常规配置好MySQL: (注:5.6版本的 data文件夹与 my.ini文件在C: ...

  7. BZOJ5090: [Lydsy1711月赛]组题(01分数规划)

    5090: [Lydsy1711月赛]组题 Time Limit: 1 Sec  Memory Limit: 256 MBSubmit: 785  Solved: 186[Submit][Status ...

  8. 升级到SQL Server 2012/2014时一些需要考虑的事项

    1. 使用Upgrade Adviser评估升级前需要解决的事情. https://msdn.microsoft.com/zh-cn/library/ms144256(v=sql.110).aspx ...

  9. prisma graphql 工具基本使用

    项目使用docker-compose mysql 运行 安装 npm insatll -g prisma or yarn global add prisma 创建代码 项目结构 ├── README. ...

  10. Minio Bucket 通知试用&&说明

    kafka 安装 docker run -p 2181:2181 -p 9092:9092 \ --name kafka --rm \ --env ADVERTISED_HOST=HOSTIP \ - ...