前言
我一直认为WEB API设计是后端工程师的活,对WEB API设计规范理解的不是很深,正是因为之前看过不同后端工程师的Web API设计难以对接前端产品,导致经常需要修改接口,浪费了很多时间,专门抽点时间去研究一下。
WEB API ≈ HTTP JSON API
常见设计方式
- HTTP SOAP API
已经过时了,也就是使用XML文件格式的数据交互方式。
HTTP JSON API ≠ JSON-RPC API ,JSON-RPC API是使用JSON文件格式在RPC协议上进行通信。
- RESTful API
REST API:REST = Representational State Transfer(代表性状态转移)是一种适用于互联网的Web服务的体系结构。
RESTful API:一个符合REST的约束条件和原则的Web服务体系结构。
所有RESTful API都是REST API,但并非所有REST API都是RESTful。
REST API是Web API设计的一种规范或者指导原则,而RESTful API则是这中架构设计原则或者规范的一种具体实现方式。
RESTful API模型:理查森成熟度模型。
级别0:任何系统的所有API都具有单个端点的系统(SOAP或RPC属于此类别)。
0级API像电脑操作系统中Shell命令语句,简单精炼。
例子:以服务名称的web服务接口。
### 请求
GET /getNewsList HTTP/1.1
### 响应 HTTP/1.1 200
content-type: application/json; charset=utf-8
{
"code":"200"
...
}
客户端仅处理响应主体的响应码,不严谨。
级别1:url资源。这是一个定义多个基于实体的URI的系统(而不是像0级系统那样具有单个端点)。这些URI可以使用不同的http操作(POST,GET,PUT等)来针对该资源实施不同的操作。
例子:以url资源划分的web服务接口。
### 请求
GET /news/getList HTTP/1.1
### 响应
HTTP/1.1 200
content-type: application/json; charset=utf-8
{
"code":"200"
...
}
客户端仅处理响应主体的响应码,不严谨。
级别2:http响应码,在级别一的基础上,使用http请求方法与响应码。
例子:以标准HTTP方法/动词和多状态代码的web服务接口。
### 请求
PUT /news/list/{id} HTTP/1.1
### 响应
HTTP/1.1 201 content-type: application/json; charset=utf-8
{
"code":"0000"
...
}
客户端使用现有的HTTP状态码并配合响应主体的响应码一起返回响应主体,区分业务响应码或HTTP状态码。
级别3:超媒体控制(指各种资源(图片、视频和文本)的链接内容),在级别二的基础上,通过响应JSON里面的Link告知请求地址,动态填充请求地址。
HATEOAS = Hypermedia As The Engine Of Application State (超媒体即应用状态引擎)
例子:以减少url资源破坏而动态返回其他url资源的web服务接口。
### 请求
GET /news/list/{id} HTTP/1.1
### 响应
HTTP/1.1 200
content-type: application/json;
charset=utf-8
{
"code":"0000",
"new": {
"content":"This is a new.",
"links": [
{
"href":"/news/list/123/collect",
"rel":"self",
"type":"POST"
},
{
"href":"/news/list/123/like",
"rel":"self",
"type":"POST"
}
]
}
}
href:检索资源的路径。(绝对路径/相对路径)
rel:relationship,关系英文单词简写,当前资源与目标资源的关系。
type:http请求方法。
HATEOAS API格式规范尚未统一,主流有两种设计规范,一种是RFC 5988规范,一种是JSON Hypermedia API Language规范。这两种规范仅供参考,并非标准统一格式。但是HATEOAS API设计可以确定的是响应的JSON必定有一个Link字段。
虽然可以将级别一,级别二和级别三视为REST,但只有更严格的级别(即级别二和级别三)才被认为是RESTful。
GraphQL API
GraphQL API 是一种为你的 API 而生的查询语言。
优点
- 精准获取数据结构,类型。
- 无需版本化API。
缺点
- 单一链接,无法遵循HTTP规范进行缓存。
- 错误处理只能通过响应体返回错误,无法在请求http响应码处理。
- 容易受到DDOS攻击。
- 增加服务端查询压力。(每次都要把字段query一遍)
- 增加学习成本。(把简单问题复杂化)
GraphQL API是基于REST API的另一种设计(实现)方式,本质上还是REST API。
使用GraphQL API需要三思而行,在实际大型复杂项目不建议使用。
注意事项
1.交互数据统一规范。
- 统一编码方式。
- 统一数据格式。
- 统一使用驼峰式单词。
避免数据乱码或出错,便于web应用维护。
2.接口命名统一规范。
- 统一小写字母。
- 注意以资源名词命名。
- 注意语义化。
- 注意分层对象。
- 注意实体类(DAO)对应关系。
- 注意复数资源名词。
避免过分简写单词,导致语义不明。
避免使用动词命名。
控制API地址长度。
延伸:
资源名词:
3.版本化API
- URI版本控制
### 请求
GET /v1/new/getList HTTP/1.1
...
- 请求头自定义字段版本控制
### 请求
GET /new/getList HTTP/1.1
Custom-version:1.0
...
- 请求头Accept字段版本控制
### 请求
GET /new/getList HTTP/1.1
Accept: application/vnd.heroku+json; version=1.0
...
推荐采用Accept字段追加版本号。
4.请求头设置Request-ID。
### 请求
GET /v1/new/getList HTTP/1.1
X-Request-ID: xkdkku7s4
X-Correlation-Id: v6pgkod-0o3
X-Trace-Id: f058eb5456
...
便于请求追踪,调试。
5.请求头设置缓存。
### 请求
GET /v1/new/getList HTTP/1.1
Cache-Control: public, max-age=5000ETag: AP_uJh8uaNcr5sdt_OO8MoxNLh7K
If-Modified-Since: Wed,21Oct201907:28:00GMT
...
便于缓存前端资源,提高用户体验。
建议
具体问题具体分析,采用什么样的接口形式应该根据业务需求而设计,切忌把简单的东西复杂化。