简介

Spring'scentral class for synchronous client-side HTTP access.It simplifies communication with HTTPservers, and enforces RESTful principles. Ithandles HTTP connections, leaving application code to provide URLs(with possible template variables) andextract results.

简单说就是:简化了发起HTTP请求以及处理响应的过程,并且支持REST。为什么说简化了呢?

来看两种实现方式

(1)使用java.net包下的URLConnection建立连接

String result= "";
BufferedReaderin = null;
try {
String urlNameString= url +"?" + param;
URL realUrl= new URL(urlNameString);
// 打开和URL之间的连接
URLConnectionconnection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept","*/*");
connection.setRequestProperty("connection","Keep-Alive");
connection.setRequestProperty("user-agent",
"Mozilla/4.0(compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立实际的连接
connection.connect();
// 获取所有响应头字段
Map<String,List<String>> map = connection.getHeaderFields();
// 遍历所有的响应头字段
for(String key : map.keySet()) {
System.out.println(key+ "--->" + map.get(key));
}
// 定义 BufferedReader输入流来读取URL的响应
in =new BufferedReader(newInputStreamReader(
connection.getInputStream()));
String line;
while ((line = in.readLine())!= null) {
result += line;
}
} catch (Exception e) {

}
// 使用finally块来关闭输入流
finally{
// 关闭流
}

(2)使用RestTempalte

ResponseEntity<SsoUrlPrm>result = restTemplate.getForEntity(requestPathUrl,SsoUrlPrm.class);  

对外开放的接口

(1)

DELETE delete
GET getForObject
  getForEntity
HEAD headForHeaders
OPTIONS optionsForAllow
POST postForLocation
  postForObject
PUT put
any exchange
  execute

(2)每一个小类又分三种,这三种有什么区别?

* 第一种和第二种的首个参数都是用String表示一个URI。但它们的最后一个参数分别是Object[]和Map
* 第三种的首个参数使用java.net.URI表示一个URI。且只有两个参数

这是因为,String类型的URI支持占位符。比如:

restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}",String.class,"42", "21");

那么最终访问的URI为:http://example.com/hotels/42/bookings/21

但是String有一个小缺陷:String形式的URI会被URL编码两次(URL encode请自行百度),这就要求服务器在获取URI中的参数时主动进行一次解码,但如果服务的提供者不这么做呢?

这时就需要使用不会使用任何编码的java.net.URI

PS:参数‘Class<T>  responseType’定义了返回数据的类型。

(3)Exchange

  与其它接口的不同:

>允许调用者指定HTTP请求的方法(GET,POST,PUT等)

>可以在请求中增加body以及头信息,其内容通过参数‘HttpEntity<?>requestEntity’描述

>exchange支持‘含参数的类型’(即泛型类)作为返回类型,该特性通过‘ParameterizedTypeReference<T>responseType’描述。比如:

List<String> a = new ArrayList<String>();
System.out.println(a.getClass());
System.out.println(a.getClass().getGenericSuperclass());
ParameterizedTypeReference pt = new ParameterizedTypeReference<ArrayList<String>>() {};
System.out.println(pt.getType());

得到的结果是:

class java.util.ArrayList
java.util.AbstractList<E>
java.util.ArrayList<java.lang.String>

这是因为ParameterizedTypeReference<ArrayList<String>>并不根据实参而是使用getGenericSuperclass()方法获取其父类的类型(注意这里的new有花括号,是ParameterizedTypeReference的子类),父类的类型通过java.lang.reflect.Type描述,然后通过Type的getActualTypeArguments()获得了父类的实参类型,注意得到的Type类,并不是class类。

(4)excute

所有的get、post、delete、put、options、head、exchange方法最终调用的都是excute方法。举个栗子:
@Override
public <T> T getForObject(String url, Class<T> responseType, Object... urlVariables) throws RestClientException {
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
HttpMessageConverterExtractor<T> responseExtractor =
<span style="white-space:pre"> </span>new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor, urlVariables);
}

Excute方法只是将String格式的URI转成了java.net.URI,之后调用了doExecute方法。整个调用过程

6.doExcute

6.1 定义
protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback,ResponseExtractor<T> responseExtractor) throws RestClientException {…} 
这里需要了解两个类: RequestCallback &ResponseExtractor
 
6.2 RequestCallback
Callback interface for code that operates on a ClientHttpRequest. Allows to manipulate the request headers, and write to the request body.
简单说:用于操作请求头和body,在请求发出前执行。

该接口有两个实现类:

AcceptHeaderRequestCallback 只处理请求头,用于getXXX()方法。
HttpEntityRequestCallback 继承于AcceptHeaderRequestCallback可以处理请求头和body,用于putXXX()、postXXX()和exchange()方法。

* DELETE、HEAD、OPTIONS没有使用这个接口。

 
6.3 发起请求
 
6.4 ResponseExtractor
6.4.1 定义
Generic callback interface used by RestTemplate's retrieval methods Implementations of this interface perform the actual work of extracting data from a ClientHttpResponse, but don't need to worry about exception handling or closing resources.
简单说:解析HTTP响应的数据,而且不需要担心异常和资源的关闭。
 
该接口有三个实现类:
HeadersExtractor 用于提取请求头。
HttpMessageConverterExtractor 用于提取响应body。
ResponseEntityResponseExtractor 使用HttpMessageConverterExtractor提取body(委托模式),然后将body和响应头、状态封装成ResponseEntity对象。
6.4.2 提取响应body
提取分三步:
(1)提取器HttpMessageConverterExtractor寻找可用的转化器
在默认的RestTemplate的构造函数中初始化了转化器集合,包括:

转化器

可转化的类型
ByteArrayHttpMessageConverter byte[]
StringHttpMessageConverter String
ResourceHttpMessageConverter Resource
SourceHttpMessageConverter javax.xml.transform.*
AllEncompassingFormHttpMessageConverter MultiValueMap
Jaxb2RootElementHttpMessageConverter XmlRootElement,XmlType(注解)
...  
MappingJackson2HttpMessageConverter Json

除了前五个,其他的转化器会由classloader尝试加载某个类来判断工程是否包含某个包,而后决定是否加入转化器集合。
提取器遍历转化器集合以查找可用的转化器,其中MappingJackson2HttpMessageConverter总是在最后一个,因为该类实现了GenericHttpMessageConverter,算是一个通用转化器,只有在找不到合适的转化器时才轮到它。Spring提供了一个该类的实现,以保证总是能得到该类。

(2)转化器寻找可用的反序列化器

转化器持有一个反序列化器缓存集合,首先从缓存中寻找
如果已有可用的反序列化器,则直接返回。否则创建一个新的反序列化器。
 
反序列化器保存着待反序列化类的域、方法、构造器等信息,反序列化时就是使用构造器创建了一个新的实例。
以jackson为例,创建反序列化器的过程在jackson-databind-xxx.jar中,有兴趣的可以看一下。调用栈如下(由下往上找):
BeanDeserializerFactory.addBeanProps/addObjectIdReader/addReferenceProperties/addInjectables
BeanDeserializerFactory.buildBeanDeserializer
BeanDeserializerFactory.createBeanDeserializer
(3)反序列化器执行反序列化

TOKEN

Json的一个或一组字符
START_OBJECT {
END_OBJECT }
START_ARRAY [
END_ARRAY ]
VALUE_TRUE true
VALUE_FALSE false
...  

调用栈:

 
 

Spring RestTemplate使用教程的更多相关文章

  1. Spring Cloud 入门教程(七): 熔断机制 -- 断路器

    对断路器模式不太清楚的话,可以参看另一篇博文:断路器(Curcuit Breaker)模式,下面直接介绍Spring Cloud的断路器如何使用. SpringCloud Netflix实现了断路器库 ...

  2. Spring Cloud 入门教程(五): Ribbon实现客户端的负载均衡

    接上节,假如我们的Hello world服务的访问量剧增,用一个服务已经无法承载, 我们可以把Hello World服务做成一个集群. 很简单,我们只需要复制Hello world服务,同时将原来的端 ...

  3. Spring Cloud入门教程(二):客户端负载均衡(Ribbon)

    对于大型应用系统负载均衡(LB:Load Balancing)是首要被解决一个问题.在微服务之前LB方案主要是集中式负载均衡方案,在服务消费者和服务提供者之间又一个独立的LB,LB通常是专门的硬件,如 ...

  4. Spring cloud系列教程第十篇- Spring cloud整合Eureka总结篇

    Spring cloud系列教程第十篇- Spring cloud整合Eureka总结篇 本文主要内容: 1:spring cloud整合Eureka总结 本文是由凯哥(凯哥Java:kagejava ...

  5. Spring RestTemplate 的介绍和使用-入门

    RestTemplate是什么? 传统情况下在java代码里访问restful服务,一般使用Apache的HttpClient.不过此种方法使用起来太过繁琐.spring提供了一种简单便捷的模板类来进 ...

  6. Spring RestTemplate: 比httpClient更优雅的Restful URL访问, java HttpPost with header

    { "Author": "tomcat and jerry", "url":"http://www.cnblogs.com/tom ...

  7. Spring Data Solr教程(翻译) 开源的搜索服务器

    Solr是一个使用开源的搜索服务器,它采用Lucene Core的索引和搜索功能构建,它可以用于几乎所有的编程语言实现可扩展的搜索引擎. Solr的虽然有很多优点,建立开发环境是不是其中之一.此博客条 ...

  8. Spring MVC 入门教程示例 (一)

    今天和大家分享下  Spring MVC  入门教程 首先还是从 HelloWorld  web 工程开始 -------------------------- 1.首先创建一个Maven Web工程 ...

  9. Spring Data JPA教程, 第三部分: Custom Queries with Query Methods(翻译)

    在本人的Spring Data JPA教程的第二部分描述了如何用Spring Data JPA创建一个简单的CRUD应用,本博文将描述如何在Spring Data JPA中使用query方法创建自定义 ...

随机推荐

  1. 微信小程序开发及相关设置小结

    今年过年,主要看了<奇葩说>和<电锯惊魂>,很不错,好东西的确需要留出足够的时间来看,匆匆忙忙走马观花是对作者的不尊重.除此之外,就是研究了一下微信小程序开发,先说对小程序的看 ...

  2. [Algorithm] Write your own Math.pow function in Javascript, using Recursive approach

    /**@abstract * Write your own Math.pow(a int, b int) function * */ function pow (a, b) { let result ...

  3. 初探 hexo博客

    近期两天迷上了hexo和gitcafe.最终搭建好了自己的个人主页.以后也能够用那个来写博客啦~直接用的gitcafe的二级域名和server,(gitcafe的server在国外.速度也挺快的),h ...

  4. PS中标尺工具在哪里

    打开photoshop应用程序,然后在PS菜单中点击“视图——标尺”选项即可打开ps标尺栏. 单位设置:      按Ctrl+K快捷键会弹出“首选项”对话框,你选择“单位与标尺”项,在“单位”一栏里 ...

  5. 【CSWS2014 Summer School】深度问答技术及其在搜索中的应用-马艳军

    Title: 深度问答技术及其在搜索中的应用 马艳军博士, 百度 Abstract: 深度问答(DeepQA)是一种基于对自然语言深度理解的智能问答技术,其核心技术涉及知识图谱建设.语义表示和计算.语 ...

  6. JavaScript三(语法、关键保留字及变量)

    基本概念 一.区分大小写 在ECMAScript中的一切(变量.函数名.操作符)都是区分大小写的. 如变量名test和Test分别表示两个不同的变量, 二.标识符 所谓标识符,就是指变量.函数.属性的 ...

  7. java面试第十五天

    网络编程: 多线程+网络: 1.服务器端的等待客户连接代码( while(true) ),服务器端与单个客户端交互的代码放入线程体( run ) 2.客户端如有其他要求,与服务器交互的代码也要放入线程 ...

  8. Protobuf学习 - 入门(转)

    从公司的项目源码中看到了这个东西,觉得挺好用的,写篇博客做下小总结.下面的操作以C++为编程语言,protoc的版本为libprotoc 3.2.0. 一.Protobuf? 1. 是什么?  Goo ...

  9. Oracle 12c CDB PDB

    先说基本用法: 先按11G之前进行 conn / as sysdba; create user test identifed by test; ORA-65096: 公用用户名或角色名无效. 查官方文 ...

  10. winform网络编程之TcpClient类,TcpListener类和UdpClient类

    TcpClient类和TcpListener类 (1)TcpClient的用途: 用于在同步阻止模式下通过网络来链接.发送和接受流数据,在此情况下,必须有侦听此连接的请求,而侦听的任务就交给TcpLi ...