资源的自我描述
资源的自我描述意思是资源可以告诉用户如何使用 API,如何与 API 交互,使得用户不查文档,也知道下一步应该做什么和能做什么。这种做法叫做 HATEOAS(Hypertext As The Engine Of Application State),中文翻译为“将超媒体格式作为应用状态的引擎”,核心思想就是每个资源都有它的状态,不同状态下,可对它进行的操作不一样。
统一接口: 这里分为4点,它们是: 资源标识符(URI),资源的操作(也就是方法Method,HTTP动词), 自描述的响应(可以认为是媒体类型Media-Type),以及状态管理(超媒体作为应用状态的引擎 HATEOAS,Hypermedia as the Engine of Application State);
0级(Plain Old XML沼泽):这里HTTP协议只是被用来进行远程交互,协议的其余部分都用错了,都是RPC风格的实现(例如SOAP,尤其是使用WCF的时候);
1级(资源):这级里,每个资源都映射到一个URI上了,但是HTTP方法并没有正确的使用,结果的复杂度不算太高;
2级(动词):正确使用了HTTP动词,状态码也正确的使用了,同时也去掉了不必要的变种;
3级(超媒体):API支持超媒体作为应用状态的引擎 HATEOAS,Hypermedia as the Engine of Application State,引入了可发现性。
什么是 RESTful
首先 REST 是 “Representational State Transfer” 的缩写,翻译为中文就是“表述性状态转移”,它是一种架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件,这套风格描述了网络资源是如何定义和寻址的。一个实现了 REST 这套风格(原则/约束)的服务就叫做 RESTful 的服务。
REST 风格(原则/约束)
如果还是不能理解上述所说的“什么是 RESTful”,那我把上述所说的合并成简洁的一句话:“URL 定位资源,用 HTTP 描述对资源操作和结果,以及资源的自我描述”。我们把这句话再详细的一一分解。
URL: API 与用户通信总是使用
HTTPS
协议; 尽量将 API 部署在专属域名下https://api.example.com
,也可以放在主域名下https://www.example.com/api
; 如有版本信息一般放在 url 中https://api.example.com/v3
,也可以放在头信息中,例如https://api.github.com
的 v3 版本 REST API 时,Accept: application/vnd.github.v3+json
。定位资源: 首先资源它是个东西,不是动作,所以用名词表示,而且资源往往与数据库的表对应,数据库中的表都是同种东西的集合,所以名词一般也是复数
https://api.example.com/v3/departments
(资源名是否复数还是根据个人习惯吧); 另外命名应该可以体现资源的结构https://api.example.com/v3/departments/{departmentId}/emoloyees
,这就表示了部门(department)和员工(employee)之前是主从关系,而https://api.example.com/v3/department/{departmentId}/emoloyees/{employeeId}
,就表示了该部门下的某个员工; 如果记录数量很多,服务器不可能都将它们返回给用户,API 应该提供过滤参数,过滤返回结果,https://api.example.com/v3/departments?page=2&per_page=15
。用 HTTP 描述对资源操作 对资源操作,用 HTTP 动词描述,HTTP 动词常见的有五个分别是: POST(创建资源)、 DELETE(删除资源)、 PUT(整体更新)、 PATCH(局部更新)、 GET(获取资源)。
POST https://api.example.com/v3/departments
:创建一个部门DELETE https://api.example.com/v3/departments/{id}
:删除指定部门PUT https://api.example.com/v3/departments/{id}
:更新指定部门的全部信息PATCH https://api.example.com/v3/departments/{id}
:更新指定部门的局部信息GET https://api.example.com/v3/departments
: 获取所有部门GET https://api.example.com/v3/departments/{id}
:获取指定部门用 HTTP 描述对资源操作的结果 服务器返回的数据格式,应该尽量使用JSON,避免使用XML; 针对不同操作,服务器向用户返回的结果应该符合规范:POST ---- 返回新生成的资源对象、DELETE ---- 返回一个空文档、PUT ---- 返回完整的资源对象、PATCH ---- 返回完整的资源对象、GET(s) ---- 返回资源对象的列表(数组)、GET ---- 返回单个资源对象; 要正确提供状态码,状态码是非常重要的,因为只有状态码会告诉 API 的使用者,请求是否如预期的成功或者失败,如果出现了错误,谁该为这个错误负责; 如果状态码是 4xx,就应该向用户返回出错信息。一般来说,返回的信息中将error作为键名,出错信息作为键值即可
{ error: "Invalid API key" }
。POST https://api.example.com/v3/departments
:创建一个部门,201,返回新创建的部门DELETE https://api.example.com/v3/departments/{id}
:删除指定部门,204 ,返回一个空文档PUT https://api.example.com/v3/departments/{id}
:更新指定部门的全部信息,201,返回更新完成的部门信息PATCH https://api.example.com/v3/departments/{id}
:更新指定部门的局部信息,201,返回更新完成的部门信息GET https://api.example.com/v3/departments
: 获取所有部门,200 ,返回部门集合,找不到返回 404GET https://api.example.com/v3/departments/{id}
:获取指定部门,200 ,返回一个所指定的部门,找不到返回 404下面再列举一下 常见会用到的状态码: 200级别,表示成功:
400级别,表示客户端引起的错误:
500级别,服务器错误:
状态码的完全列表参见这里。
资源的自我描述 资源的自我描述意思是资源可以告诉用户如何使用 API,如何与 API 交互,使得用户不查文档,也知道下一步应该做什么和能做什么。这种做法叫做 HATEOAS(Hypertext As The Engine Of Application State),中文翻译为“将超媒体格式作为应用状态的引擎”,核心思想就是每个资源都有它的状态,不同状态下,可对它进行的操作不一样。
上面代码表示,文档中有一个 links 属性,用户读取这个属性就知道下一步应该做什么和能做什么了。每个 link 中 rel 表示这个 link 与当前资源的关系, href 表示 link 的 URL,method 表示这个 link 的 HTTP 动词。
其实上述描述的是 REST 风格(原则/约束)最重要的原则之一,统一接口。REST 有 6 大原则/约束:
Richardson 成熟度模型
Richardson 成熟度模型代表着你的API是否足够成熟,分为4个级别,0代表最差,3代表最好。
0级(Plain Old XML沼泽):这里HTTP协议只是被用来进行远程交互,协议的其余部分都用错了,都是RPC风格的实现(例如SOAP,尤其是使用WCF的时候); 1级(资源):这级里,每个资源都映射到一个URI上了,但是HTTP方法并没有正确的使用,结果的复杂度不算太高; 2级(动词):正确使用了HTTP动词,状态码也正确的使用了,同时也去掉了不必要的变种; 3级(超媒体):API支持超媒体作为应用状态的引擎 HATEOAS,Hypermedia as the Engine of Application State,引入了可发现性。
我觉得 Richardson 成熟度模型也可以用这句话描述:“URL 定位资源,用 HTTP 描述对资源操作和结果,以及资源的自我描述”
只有满足了 6 个原则成熟度到 3 级系统才可以真正称得上是 RESTful 的,其实大部分系统的 RESTful API 并不是 RESTful 的,成熟度只做到 2 级(URL 定位资源,用 HTTP 描述对资源操作和结果) 但这样并不代表这些 API 就不好,REST 只是一种风格,不是规范,利弊需要开发人员去衡量。