REST 这个概念于 2000 年由 Roy Fielding 在就读加州大学欧文分校期间在学术论文“Architectural Styles and the Design of Network-based Software Architectures”首次提出,现在Rest通过 JSR-311 成为了 Java™ 6 不可或缺的部分。

Rest是一种设计风格,不是一个标准,这意味着开发人员定义的api接口可以不按照rest 风格,rest 风格可以应用于各种无状态协议的接口设计。Rest 通常使用HTTP 协议作为传输协议

rest 风格(representation state transfer 资源表现层状态转移) 如何定义一个接口:

  • 系统中的每一个对象或是资源都可以通过一个唯一的 URI 来进行寻址,URI 的结构应该简单、可预测且易于理解,比如定义目录结构式的 URI,每一个URI代表一种资源,独一无二
  • 以遵循 RFC-2616 所定义的协议的方式显式地使用 HTTP 方法,建立创建、检索、更新和删除(CRUD:Create, Retrieve, Update and Delete)操作与 HTTP 方法之间的一对一映射:客户端通过四个动词,对服务器端资源进行操作,实现"表现层状态转化"
  • 若要在服务器上创建资源,应该使用 POST 方法;
  • 若要检索某个资源,应该使用 GET 方法;
  • 若要更改资源状态或对其进行更新,应该使用 PUT 方法;
  • 若要删除某个资源,应该使用 DELETE 方法。
  • URI 所访问的每个资源都可以使用不同的形式加以表示(比如 XML 或者 JSON),具体的表现形式取决于访问资源的客户端,客户端与服务提供者使用一种内容协商的机制(请求头与 MIME 类型)来选择合适的数据格式,最小化彼此之间的数据耦合。客户端和服务器之间,传递这种资源的某种表现层:xml ,json,text   表现层

注意点:

  • URI中不应该包含动词。资源表示的一种实体,应该都是名词。只能用HTTP请求方法表示资源操作动作。

    例如/posts/show/1 应该改为/posts/1  用GET方法表明是show操作。

  • 有些难以用请求方法直接表达的动作可以换成名词,作为服务性的资源。

    例如 transfer动作   可以修改为POST /transaction  from=1&to=2&amout=100.00

  • URI中不应该包含版本号。不同的版本其实是同一种资源的不同表现层,所有应该使用同一个URI。版本号在HTTP请求头的Accept字段中区分(参考 http://www.informit.com/articles/article.aspx?p=1566460)。

    例如

      http://www.example.com/app/1.0/foo

      http://www.example.com/app/2.0/foo

    在请求头中区分:

      Accept: vnd.example-com.foo+json; version=1.0

      Accept: vnd.example-com.foo+json; version=2.0

 

REST风格接口的其他要求

  • 必须是客户端和服务器结构
  • 使用的连接协议具有无状态性,例如http
  • 接口能够利用Cache机制增进性能,服务器返回信息必须被标记是否可以缓存,如果缓存,客户端可能会重用之前的信息发送请求。
  • 接口定义成层次化的系统:系统组件不需要知道与他交流组件之外的事情。封装服务,引入中间层
  • 统一接口(Uniform Interface),看接口名称 ,方法就知道接口作用。
  • 支持按需代码(Code-On-Demand 可选)

REST的优点

  • 浏览器即可作为客户端,简化软件需求
  • 通讯本身的无状态性可以让不同的服务器的处理一系列请求中的不同请求,提高服务器的扩展性
  • 可更高效利用缓存来提高响应速度
  • 限制了系统的复杂性,提高可扩展性
  • 不需要额外的资源发现机制
  • 资源描述与视图的松耦合
  • 可提供OpenAPI,便于第三方系统集成,提高互操作性;例如java rs就是openapi resteasy 就是三方系统

应用于 Web 服务

符合 REST 设计风格的 Web API 称为 RESTful API。它从以下三个方面资源进行定义:

  • 直观简短的资源地址:URI,比如:http://example.com/resources/
  • 传输的资源:Web服务接受与返回的互联网媒体类型,比如:JSONXML ,YAML 等。
  • 对资源的操作:Web服务在该资源上所支持的一系列请求方法(比如:POST,GET,PUT或DELETE)。

下表列出了在实现 RESTful API 时 HTTP 请求方法的典型用途。

[1] HTTP 请求方法在 RESTful API 中的典型应用

资源

GET

PUT

POST

DELETE

一组资源的URI,比如http://example.com/resources/

列出 URI,以及该资源组中每个资源的详细信息(后者可选)。

使用给定的一组资源替换当前整组资源。

在本组资源中创建/追加一个新的资源。 该操作往往返回新资源的URL。

删除 整组资源。

单个资源的URI,比如http://example.com/resources/142

获取 指定的资源的详细信息,格式可以自选一个合适的网络媒体类型(比如:XML、JSON等)

替换/创建 指定的资源。并将其追加到相应的资源组中。

把指定的资源当做一个资源组,并在其下创建/追加一个新的元素,使其隶属于当前资源。

删除 指定的元素。

PUT 和 DELETE 方法是幂等方法。GET方法是安全方法 (不会对服务器端有修改,因此当然也是幂等的)。

不像基于SOAP的Web服务,RESTful Web服务并没有的“正式”标准[2]。 这是因为REST是一种架构,而SOAP只是一个协议。虽然REST不是一个标准,但在实现RESTful Web服务时可以使用其他各种标准(比如HTTP,URL,XML,PNG等)。

实现举例

例如,一个简单的网络商店应用,

列举所有商品,

GET http://www.store.com/products

呈现某一件商品,

GET http://www.store.com/product/12345

下单购买,

POST http://www.store.com/order
<purchase-order>
  <item> ... </item1>
</purchase-order>

默认所有输入输出均为JSON格式。一个例外:GET请求的参数为URL参数
出错代码一律使用HTTP标准错误码,参见HTTP 标准状态码

修改用户:

    URL: POST /mm/v1/crm/customer/[customer id]
输入:
参数名 参数类型 说明 必填 默认值 限制
name string 客户名称 是   
interface_person string 对接人姓名 是   
interface_phonenumber string 对接人电话 是   
interface_email string 对接人邮箱 是   

输出:
参数名 参数类型 说明 样例值
id int 客户ID 10001
name string 客户名称 银行
interface_person string 对接人姓名 小明
interface_phonenumber string 对接人电话 12345678
interface_email string 对接人邮箱 misdfu@asdfasdf.com
create_time date 客户创建时间 2015-04-01 12:34:56

获得所有可编辑权限
URL: GET /mm/v1/crm/permission
输入
输出
一个数组。每个元素代表一个可编辑的权限项,格式如下
参数名 参数类型 说明 样例值
id int 权限ID 1
name string 权限名称 DEMO APP

删除用户

URL:DELETE /mm/v1/crm/customer/[customer id]
输入:无
输出:
参数名     参数类型     说明                 样例值
id             int      成功删除的客户ID     10001

http无状态概念理解

1》官方说法:

1.协议对于事务处理没有记忆能力

2.对同一个url请求没有上下文关系

3.每次的请求都是独立的,它的执行情况和结果与前面的请求和之后的请求时无直接关系的,它不会受前面的请求应答情况直接影响,也不会直接影响后面的请求应答情况

4.服务器中没有保存客户端的状态,客户端必须每次带上自己的状态去请求服务器

2》理解

标准的http协议指的是不包括cookies,session,application的http协议

服务上肯定有用户的数据,所以这里中的状态不是指用户的数据,无状态是没有对本次会话设置一个缓存区,记录这次会话的状态,缓存区包括服务端和用户端,这个状态就是客户端和服务器在临时会话中产生的数据(实现这些东西所凭借的后面的缓存空间中的客户的临时数据)

3》例子理解

假设没有cookie和session只有http的时候,当一个注册用户访问这个购物网站的时候,发生的情况

1.前提情况:

服务器为每个注册用户建立了数据表,记录用户的数据

http是无连接的

2.第一步需要登录

用户通过http把用户的用户名和密码发给服务器,服务器把他们跟自己存有的用户资料对比,如果一致返回信息登录成功

3.然后用户点击某一商品页

相当于输入一个商品页的网址,假设商品页比较机密不对外公开,需要是用户才能访问,虽然http能传送用户名和密码,而且刚才也输入了,还验证成功,但是因为服务器既不会记得你登录的状态客户端也不会存储你刚才输入的用户名和密码,所以因为这一次访问无法确定你的身份,只能访问失败。

为解决这个问题只能在你访问的网址的同时继续带上你的用户名和密码

4.现在假设,你已经选了几件商品在你的购物车中,你想再添加一件商品,于是你点击某个商品旁边的加号

这个动作相当于输入一个网址,网址的内容是发送一个请求,往你的购物车中加入这个商品

系统首先用你传来的用户名和密码验证你的身份,然后访问你的数据库,在其中的购物车属性下加一条数据,就是这个商品的数据,操作结束后,返回操作结束,并结束访问

虽然可以解决但是会有三个很大的问题

1.每访问一次需要权限的内容都需要在客户端输入用户名和密码,多次少量的访问存在非常大的性能浪费。就会想到一次大量的操作更加有效率,就是很容易想到了缓存区(cookie解决)

2.每一次操作都要与系统底层的数据库进行交互(session机制解决)

3.非重要琐碎数据(非重要数据)被写入数据库跟主要数据放在一起,存放这些非重要数据也很容易想到缓存区(session机制解决)