REST

名词解释

  • Representational State Transfer (资源)表现层状态转化
  • 表现层即view,状态转化指更新之后的view,这个词来自REST提出者也即http协议作者的博士论文

旨在解决什么问题

  • 现今我们用到的增删改查接口往往会设计为get、post请求,通过语义化命名接口来实现,如:
http://api.xxx.com/delete/id
http://api.xxx.com/addInfo
  • 一般会将响应设计为如下形式:
{
    code:20002,
    msg:{
        data:data
    }
}
  • 上述做法把http协议只作为了传输协议,http状态码,http method的语义定义都没有用起来,换句话说,REST设计者认为大家一直在错误使用http协议,于是提出了REST API设计风格和原则
  • REST指的是一种设计API的理念、风格或者模式,它不是协议,非强制性
  • 形而上的总结为:语义化http接口设计规范

实现

  • REST的做法是:用URL定位资源,用HTTP描述操作,用http状态码表示结果
  • 有人总结为:接口url尽量不出现动词,只用来表示资源,这符合URL的定义,http协议使用的get、post、put、delete、update来表示增删改查CRUD(Create/Read/Update/Delete),用http状态码也符合http状态码的定义
  • 有人认为http状态码与响应中包装的code码不矛盾,协议层错误和响应码的错误理应分层处理

特征

  • REST之前用的是SOAP设计模式,它把http作为传输协议,在其上建立自己的协议
  • REST则把http作为应用层协议,实现了http协议设计的初衷
  • SOAP是面向服务的,REST是面向资源的
<!--SOAP将用户操作看成是服务-->
post /users/getUser
post /users/creatUser
post /users/updateUser
post /users/deleteUser

<!--REST将用户看作一种资源-->
get /users/{userId} // 获取userId对应的user信息
post /users //创建一个新的user
put /users/{userId} // 更改userId对应的user信息
delete /users/{userId} //删除userId对应的user。

幂等性

  • 幂等性是http设计的语义规范,并非RESTful风格的要求,是分布式系统的特征
  • HTTP方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用
  • 注意副作用指的是服务器的状态变化,副作用不是结果,如
    1. get 无副作用,每次请求服务端状态不变,幂等
    2. delete 有副作用,但副作用相同,每次都是删除该资源,幂等
    3. post 和 put容易混淆,都有副作用,但post不幂等、put幂等
      • post创建资源、put更新资源的总结并不正确,二者都可以创建
      • POST所对应的URI并非创建的资源本身,而是资源的接收者。比如POST的http://www.forum.com/articles 的语义是在 http://www.forum.com/articles 下创建一篇帖子,HTTP响应中应包含帖子的创建状态以及帖子的URI。两次相同的POST请求会在服务器端创建两份资源,它们具有不同的URI,post不幂等
      • 而PUT所对应的URI是要创建或更新的资源本身。比如PUT的 http://www.forum/articles/4231 的语义是创建或更新ID为4231的帖子。对同一URI进行多次PUT的副作用和一次PUT是相同的,put是幂等的
      • 可以看出,post和put对服务端URI的影响是不一样的,这是判断副作用是否相同的标志

使用注意事项

  • 要前后端协作,框架支持
  • 具体原则是:

    • URI不要使用动词,资源是名次的描述,http动词表示操作
    • 不要携带版本号,版本是资源的不同表现形式,版本号应放在header中
    • 路径复数
    • 参数用来过滤:?page=2&per_page=100
    • 业务逻辑错误处理最好不要用code码,用错误信息
    • 超媒体Hypermedia API:即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么

      {"link": {
      "rel":   "collection https://www.example.com/zoos",
      "href":  "https://api.example.com/zoos",
      "title": "List of zoos",
      "type":  "application/vnd.yourformat+json"
      }}