转载来源:https://www.cnblogs.com/zhaoyan001/p/8442602.html

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

        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);  

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

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 RestTemplate详解

    Spring RestTemplate详解   1.什么是REST? REST(RepresentationalState Transfer)是Roy Fielding 提出的一个描述互联系统架构风格 ...

  2. 【Spring】Spring AOP详解(转载)

    一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址:http://www.cnbl ...

  3. Spring AOP详解(转载)所需要的包

    上一篇文章中,<Spring Aop详解(转载)>里的代码都可以运行,只是包比较多,中间缺少了几个相应的包,根据报错,几经百度搜索,终于补全了所有包. 截图如下: 在主测试类里面,有人怀疑 ...

  4. 如约而至,Java 10 正式发布! Spring+SpringMVC+MyBatis+easyUI整合进阶篇(十四)Redis缓存正确的使用姿势 努力的孩子运气不会太差,跌宕的人生定当更加精彩 优先队列详解(转载)

    如约而至,Java 10 正式发布!   3 月 20 日,Oracle 宣布 Java 10 正式发布. 官方已提供下载:http://www.oracle.com/technetwork/java ...

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

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

  6. [转载]Spring配置文件详解一:

    原文地址:与base-package="com.xx">Spring配置文件详解一:<context:annotation-config/>与<contex ...

  7. Spring AOP详解及简单应用

    Spring AOP详解   一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址: ...

  8. 转:Spring AOP详解

    转:Spring AOP详解 一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址: ...

  9. malloc 与 free函数详解<转载>

    malloc和free函数详解   本文介绍malloc和free函数的内容. 在C中,对内存的管理是相当重要.下面开始介绍这两个函数: 一.malloc()和free()的基本概念以及基本用法: 1 ...

随机推荐

  1. 2-删除IPC$的方式

    一.使用命令临时删除IPC$的方式 1.查看IPC$是否启用 命令:net share 2.删除IPC$功能 命令:net share ipc$ /delete 注:使用命令删除后,重启服务器后,IP ...

  2. vue-cropperjs 图片裁剪上传功能使用方法记录

    引入: 官网:https://www.npmjs.com/package/vue-cropperjs 控制台输入: npm install --save vue-cropperjs vue 项目中引入 ...

  3. CSS权重;慎用!important

    初初接触样式的前端开发者在碰到样式覆盖时,最先选择的往往是!important. 但是这种做法不好,应该优先考虑从样式的级联属性或者位置来解决问题. 切记以下情况永远不要使用!important: 1 ...

  4. ACM省赛及蓝桥总结,且随疾风前行,身后亦须留心

    今年算是开始正式打比赛了,真正打起比赛来感觉的确是和平时训练不太一样,最重要的还是在心态和信心上. ACM省赛是拿下个银牌,昭哥上来就把K题金牌题给当签到题给签掉了,可惜我们没有利用好这一题.感觉第一 ...

  5. 【csp模拟赛1】T1 心有灵犀

    [题目描述] 爱玩游戏的小 Z 最近又换了一个新的游戏.这个游戏有点特别,需要两位玩 家心有灵犀通力合作才能拿到高分. 游戏开始时,两位玩家会得到同一个数字 N,假设这个数字共有 t 位数码, 然后两 ...

  6. jQuery系列(一):jQuery介绍

    1.为什么要使用jQuery (1)什么是jQuery jQuery 是 js 的一个库,封装了我们开发过程中常用的一些功能,方便我们调用,提高开发效率. js库是把我们常用的功能放到一个单独的文件中 ...

  7. JavaWeb_(Hibernate框架)Hibernate论坛项目中多对多案例

    基于SSH论坛小型项目 传送门 用户和发帖进行举例 多对多关系:多个用户可以回复多个帖子 因此引入了一张回复表,用来保存用户id和帖子id CREATE TABLE `hforum`.`answer` ...

  8. Hadoop元数据备份与恢复方案

    Hadoop元数据备份与恢复方案 标签(空格分隔): Hadoop Namenode 备份策略: 周期性备份namenode.standby namenode的dfs.namenode.name.di ...

  9. [CSP-S模拟测试]:C(倍增+数学)

    题目传送门(内部题152) 输入格式 第一行两个整数$N,Q$. 接下来一行$N$个整数,第$i$个为$a_i$. 接下来的$N-1$行,每行两个整数$u,v$.表示$u,v$之间有一条边. 接下来的 ...

  10. 【平台中间件】为什么用etcd而不用ZooKeeper?从应用场景到实现原理的全方位解读

    前言 博主在工作过程中经常接触到ETCD,搜索相关资料的时候发现排名最高的是一篇图片全是404的转载文章,后来看到了原文,感觉有义务让更多的人看到这样的精品文章,所以进行了转载. 原文发布在infoQ ...