空空叶博客 学习与开发博客

rest

2017-05-05

rest相关笔记

介绍

  • REST是设计风格而不是标准,REST通常基于使用HTTP,URI,和XML以及HTML这些现有的广泛流行的协议和标准
  • 资源是由URI来指定,每个URI唯一标识一个资源(resource),所以URI中不能有动词,只能有名词
  • 对资源的操作包括获取、创建、修改和删除资源,这些操作正好对应HTTP协议提供的GET、POST、PUT和DELETE方法
  • 通过操作资源的表现形式来操作资源
  • 资源的表现形式则是XML或者HTML,取决于读者是机器还是人,是消费web服务的客户软件还是web浏览器,当然也可以是任何其他的格式
  • 资源与URI是一对多关系;资源(resource)与资源表述(resource representation)也是一对多关系
  • 使用复数名词: 对所有资源使用复数
  • 使用Http头声明序列化格式: 在客户端和服务端,双方都要知道通讯的格式,格式在HTTP-Header中指定:
    • Content-Type 定义请求格式
    • Accept 定义系列可接受的响应格式
  • 为集合提供过滤 排序 选择和分页等功能:
    • Filtering过滤: 使用唯一的查询参数进行过滤:
      • GET /cars?color=red 返回红色的cars
      • GET /cars?seats<=2 返回小于两座位的cars集合
    • Sorting排序: 允许针对多个字段排序
      • GET /cars?sort=-manufactorer,+model 这是返回根据生产者降序和模型升序排列的car集合
    • Field selection: 移动端能够显示其中一些字段,它们其实不需要一个资源的所有字段,给API消费者一个选择字段的能力,这会降低网络流量,提高API可用性。
      • GET /cars?fields=manufacturer,model,id,color
    • Paging分页: 使用 limit 和offset.实现分页,缺省limit=20 和offset=0;
      • GET /cars?offset=10&limit=5
  • 为了将总数发给客户端,使用订制的HTTP头: X-Total-Count.

架构六约束

  • 统一接口(Uniform Interface)
    • Resource-Based
    • Manipulation of Resources Through Representations
    • Self-descriptive Messages
    • Hypermedia as the Engine of Application State (HATEOAS)
  • 客户-服务器(Client-Server)
  • 无状态(Stateless)
    • 然而,有些情况下,无状态并不适用,比如api调用速度限制,oauth的三次握手等
  • 缓存(Cacheable)
    • Response必须明确指出自己是否可被缓存
  • 分层系统(Layered System)
  • 按需代码(可选)(optional)

优点

  • 可更高效利用缓存来提高响应速度
  • 通讯本身的无状态性可以让不同的服务器的处理一系列请求中的不同请求,提高服务器的扩展性
  • 浏览器即可作为客户端,简化软件需求
  • 相对于其他叠加在HTTP协议之上的机制,REST的软件依赖性更小
  • 不需要额外的资源发现机制
  • 在软件技术演进中的长期的兼容性更好

状态

1. 应用状态(Application State)

  • 与某一特定请求相关的状态属于应用状态,而RESTful架构要求任何此类状态由请求方负责提供

2. 资源状态(Resource State)

API设计

  • 一个资源可以对应多个uri,比如www.xxx.com/users/123/orders/1www.xxx.com/orders/1可以对应同一个资源,这也是很合适的

请求头

对于REST API,有一些HTTP headers很重要

Accept(所有方法)

服务器需要返回什么样的content. 如果客户端要求返回”application/xml”,服务器端只能返回”application/json”,那么最好返回406错误. 一个合格的REST API需要根据Accept头来灵活返回合适的数据.

If-Modified-Since/If-None-Match(GET方法)

如果客户端提供了某个条件,那么当条件满足时才返回数据,否则返回304 not modified. 否则并不高效,会浪费额外的带宽.

If-Match(PUT/PATCH/DELETE方法)

进行更新或删除操作时,服务端应该要求客户端提供If-Match头(或类似的方法),只有两边的Etag一致时才进行操作,否则返回412 precondition failed

请求方法

如果操作符合幂等性,那么相同的数据和参数下,执行一次或多次产生的效果(副作用)是一样的。

GET

幂等安全

获取某个资源.

POST

非幂等不安全

创建一个新的资源。

PUT

幂等不安全

替换某个已有的资源。

DELETE

幂等不安全

删除某个资源。

成熟度级别分析

0级

服务有单个URI,使用单个HTTP动词(通常是POST)

1级

服务有多个URI,使用单个的HTTP动词(通常是POST)

2级

服务使用大量URI与多个HTTP动词

3级

最高级别,超媒体既应用状态引擎。这个意思是说,对于任何服务都存在很多子服务,你只需要知道第一个服务的入口,便可以依据服务返回结构的自描述性得到下一个服务的入口

接口版本

为什么要有版本?

比如GET接口/api/user/{id},返回用户信息,后面用户信息变了,修改了一个返回字段,那么依赖原先返回的服务就会出错,因此接口应该有版本

有哪些加版本的方式?

  1. 加版本号到URL中,如/api/v1/user/{id}
    • 这种方式语义上来说不正规,因为我要获取的是用户的信息,而不是某个版本的用户信息(即版本号与资源并无直接关系),但是十分容易使用!
  2. 加到请求头中,如api-version: 1
    • 这种方式并非语义上描述资源的方式

上一篇 oauth

下一篇 spring

目录