Spring RestTemplate详解

 

1、什么是REST?

REST(RepresentationalState Transfer)是Roy Fielding 提出的一个描述互联系统架构风格的名词。REST定义了一组体系架构原则,您可以根据这些原则设计以系统资源为中心的Web 服务,包括使用不同语言编写的客户端如何通过 HTTP处理和传输资源状态。

为什么称为 REST?Web本质上由各种各样的资源组成,资源由URI 唯一标识。浏览器(或者任何其它类似于浏览器的应用程序)将展示出该资源的一种表现方式,或者一种表现状态。如果用户在该页面中定向到指向其它资源的链接,则将访问该资源,并表现出它的状态。这意味着客户端应用程序随着每个资源表现状态的不同而发生状态转移,也即所谓REST。

附:REST定义RESTSOAP的比较

2、REST成熟度的四个层次

第一个层次(Level0)的Web 服务只是使用 HTTP 作为传输方式,实际上只是远程方法调用(RPC)的一种具体形  式。SOAP和 XML-RPC都属于此类。

第二个层次(Level1)的Web 服务引入了资源的概念。每个资源有对应的标识符和表达。

第三个层次(Level2)的Web 服务使用不同的 HTTP 方法来进行不同的操作,并且使用HTTP 状态码来表示不同的结果。如 HTTPGET 方法来获取资源,HTTPDELETE 方法来删除资源。

第四个层次(Level3)的Web 服务使用 HATEOAS。在资源的表达中包含了链接信息。客户端可以根据链接来发现可以执行的动作。

 

其中第三个层次建立了创建、读取、更新和删除(create,read, update, and delete,CRUD)操作与 HTTP方法之间的一对一映射。根据此映射:

(1)若要在服务器上创建资源,应该使用POST 方法。

(2)若要检索某个资源,应该使用GET 方法。

(3)若要更改资源状态或对其进行更新,应该使用PUT 方法。

(4)若要删除某个资源,应该使用DELETE 方法。

3、HTTP请求的方法

(1)GET:通过请求URI得到资源
(2)POST:用于添加新的内容
(3)PUT:用于修改某个内容,若不存在则添加
(4)DELETE:删除某个内容
(5)OPTIONS :询问可以执行哪些方法
(6)HEAD :类似于GET, 但是不返回body信息,用于检查对象是否存在,以及得到对象的元数据
(7)CONNECT :用于代理进行传输,如使用SSL
(8)TRACE:用于远程诊断服务器

4、HTTP请求的状态码

(1)成功Successful2xx:此类状态码标识客户端的请求被成功接收、理解并接受。常见如200(OK)、204(NoContent)。
(2)重定向Redirection3xx:这个类别的状态码标识用户代理要做出进一步的动作来完成请求。常见如301(MovedPermanently)、302(MovedTemprarily)。
(3)客户端错误Client Error 4xx:4xx类别的状态码是当客户端象是出错的时使用的。常见如400(BadRequest)、401(Unauthorized)、403(Forbidden)、404(NotFound)。
(4)服务器错误Server Error 5xx:响应状态码以5开头表示服务器知道自己出错或者没有能力执行请求。常见如500(InternalServer Error)、502(BadGateway)、504(GatewayTimeout)。

附HTTP1.1的标准简介:http://blog.chinaunix.net/uid-9188830-id-2007021.html

5、RestTemplate

5.1 简介

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建立连接

  1. String result= "";
  2. BufferedReaderin = null;
  3. try {
  4. String urlNameString= url +"?" + param;
  5. URL realUrl= new URL(urlNameString);
  6. // 打开和URL之间的连接
  7. URLConnectionconnection = realUrl.openConnection();
  8. // 设置通用的请求属性
  9. connection.setRequestProperty("accept","*/*");
  10. connection.setRequestProperty("connection","Keep-Alive");
  11. connection.setRequestProperty("user-agent",
  12. "Mozilla/4.0(compatible; MSIE 6.0; Windows NT 5.1;SV1)");
  13. // 建立实际的连接
  14. connection.connect();
  15. // 获取所有响应头字段
  16. Map<String,List<String>> map = connection.getHeaderFields();
  17. // 遍历所有的响应头字段
  18. for(String key : map.keySet()) {
  19. System.out.println(key+ "--->" + map.get(key));
  20. }
  21. // 定义 BufferedReader输入流来读取URL的响应
  22. in =new BufferedReader(newInputStreamReader(
  23. connection.getInputStream()));
  24. String line;
  25. while ((line = in.readLine())!= null) {
  26. result += line;
  27. }
  28. } catch (Exception e) {
  29. }
  30. // 使用finally块来关闭输入流
  31. finally{
  32. // 关闭流
  33. }

(2)使用RestTempalte

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

5.2 对外开放的接口

(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’描述。比如:

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

得到的结果是:

  1. class java.util.ArrayList
  2. java.util.AbstractList<E>
  3. 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方法。举个栗子:

  1. @Override
  2. public <T> T getForObject(String url, Class<T>  responseType, Object... urlVariables) throws    RestClientException {
  3. RequestCallback requestCallback =     acceptHeaderRequestCallback(responseType);
  4. HttpMessageConverterExtractor<T> responseExtractor =
  5. <span style="white-space:pre">    </span>new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
  6. return execute(url, HttpMethod.GET, requestCallback, responseExtractor, urlVariables);
  7. }

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

6.doExcute

6.1 定义
  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
...  

调用栈:

转载自:https://www.cnblogs.com/caolei1108/p/6169950.html#undefined

Spring RestTemplate详解的更多相关文章

  1. Spring RestTemplate详解(转载)

    转载来源:https://www.cnblogs.com/zhaoyan001/p/8442602.html 1.什么是REST? REST(RepresentationalState Transfe ...

  2. Spring配置文件详解 – applicationContext.xml文件路径

    Spring配置文件详解 – applicationContext.xml文件路径 Java编程                 spring的配置文件applicationContext.xml的默 ...

  3. spring配置文件详解--真的蛮详细

    spring配置文件详解--真的蛮详细   转自: http://book.51cto.com/art/201004/193743.htm 此处详细的为我们讲解了spring2.5的实现原理,感觉非常 ...

  4. 【转载】Spring AOP详解 、 JDK动态代理、CGLib动态代理

    Spring AOP详解 . JDK动态代理.CGLib动态代理  原文地址:https://www.cnblogs.com/kukudelaomao/p/5897893.html AOP是Aspec ...

  5. J2EE进阶(四)Spring配置文件详解

    J2EE进阶(四)Spring配置文件详解 前言 Spring配置文件是用于指导Spring工厂进行Bean生产.依赖关系注入(装配)及Bean实例分发的"图纸".Java EE程 ...

  6. spring事务详解(五)总结提高

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.概念 ...

  7. spring事务详解(四)测试验证

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

  8. spring事务详解(二)简单样例

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

  9. spring事务详解(三)源码详解

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

随机推荐

  1. 【转】W3C中国与百度联合组织移动网页加速技术研讨会

    2017 年 8 月 30 日,W3C 会员百度在北京中关村软件园国际会议中心主办了 "移动网页加速技术研讨会",W3C 中国以及腾讯.阿里巴巴及 UC.搜狗.小米.傲游.中国移动 ...

  2. ADB环境搭建 -- For Windows 10

    一.安装 ADB: ADB下载链接:http://adbshell.com/upload/adb.zip       ADB官网:http://adbshell.com/ 下载好后,建议直接把文件解压 ...

  3. 第10章 协议和声明类型常量 - IdentityModel 中文文档(v1.0.0)

    使用OAuth 2.0,OpenID Connect和声明时,声明类型和protocoal值有很多"魔术字符串".IdentityModel提供了几个常量字符串类来帮助它. 10. ...

  4. HTML 练习显示隐藏

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. HTML 练习实现遮罩层

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. SAP MM 标准采购组织的分配对于寄售采购订单收货的影响

    SAP MM 标准采购组织的分配对于寄售采购订单收货的影响 PO 4100004022 是一个寄售的采购订单, 采购组织是CSAS, 工厂代码SZSP.采购信息记录也是有的, MIGO试图对该采购订单 ...

  7. 4.熟悉App Inventor 2编程界面

    以下图片来自 https://www.17coding.net/的 俄罗斯方块开发笔记 的 第二章 开发与测试环境 .感谢金老师的分享. 建议大家打开上面第二章的链接,认真阅读.

  8. Android6.0 源码修改之Settings音量调节界面增加通话音量调节

    前言 今天客户提了个需求,因为我们的设备在正常情况下无法调节通话音量,只有在打电话过程中,按物理音量加减键才能出现调节通话音量seekBar,很不方便,于是乎需求就来了.需要优化两个地方 1.在正常情 ...

  9. Postgres全文搜索功能

    当构建一个Web应用时,经常被要求加上搜索功能.其实有时候我们也不知道我要搜索个啥,反正就是要有这个功能.搜索确实很重要的特性,这也是为什么像Elasticsearch和Solr这样基于Lucene的 ...

  10. 有关Windows10中诊断和反馈隐私设置

    当你使用 Windows 时,我们将收集诊断信息,为了确保能收到你(我们的客户)的反馈,我们为你提供了多种方式,以便你可以随时发送反馈,也可以在某个特定的时间(例如当 Windows 10 向你提出关 ...