欢迎访问陈同学博客原文
本文记录了 RESTful API 的一些实践经验,内容综合了部分 后端圈.研习小组 关于 REST 的探讨结果,仅简单带一下理论知识,更多可参考:
- Roy Thomas Fielding 2000年的 博士论文 中 Chapter 5: Representational State Transfer (REST)
- 阮一峰:理解 RESTful 架构
简介
REST 是 Representational State Transfer 首字母缩写,翻译为 表现层状态转化,加上主语 资源,应为:资源通过表现层进行状态转化。
例如:服务端提供接口查询单个用户,返回数据格式可以是:JSON、XML、文本、HTML等,这就是资源的表现形式。客户端通过HTTP(HTTPS)协议传递某种格式(表现层)的数据给服务端来完成对资源的状态变更。
技术团队理解并统一遵循 RESTful 接口的规范,可避免杂乱的接口定义,使得接口顾名思义,提高效率。
接口组成
接口由HTTP动词、域名、版本、Endpoint组成。
GET https://example.com/api/v1/users
Endpoint
Endpoint 在 RESTful 中理解为资源,使用复数名词来命名。例如:用户 users。
版本
表示接口版本号,可直接放入URL。例如:
/v1/users
/v2/users
也有使用自定义 HTTP Header 属性来表示版本,不过不推荐。
域名
如果使用主域名,可以在域名中加入 /api
前缀,Proxy 可根据该部分进行代理。如果使用专用域名也可以不加。
https://example.com/api 主域名
https://api.example.com API专用域名
HTTP动词
通过HTTP动词结合URL来操作资源,下面是常用用法。
HTTP 动词 | 资源 | 含义 |
---|---|---|
GET | users | 查询所有用户 |
GET | users/{id} | 查询某用户 |
GET | users/{id}/orders | 查询某用户的所有订单 |
POST | users | 新增用户 |
PUT | users/{id} | 更新某个用户信息,需提供用户改变后的所有信息 |
PATCH | users/{id} | 更新某个用户信息,只需提供改变的属性 |
DELETE | users/{id} | 删除某个用户 |
接口命名实践
实际业务中,除普通的CRUD外,会有许多其他场景,下面例举一些。
操作资源
通常会开放一些专用接口来操作资源,比如:冻结用户、解冻用户。
可将对资源的操作抽象为actions,这样通过HTTP Method + actions 就可以表示多种操作。
冻结用户
PATCH /users/1/actions/freeze
解冻用户
PATCH /users/uniqueCheck
注:团队内保持同一规范即可,也可不用actions,例如直接用 PATCH /users/1/freeze
批量操作
- 批量查询
根据用户ID批量检索用户
GET /users/actions/batchQuery?userIds=1,2,3
- 批量更新
根据用户ID批量失效用户
PATCH /users/actions/batchFreeze
检索单个资源
除根据主键检索信息外,经常会根据其他唯一字段来检索数据。例如利用手机号、邮箱检索单个用户:
GET /users/actions/singleQuery?mobile=xxx
GET /users/actions/singleQuery?mail=xxx
唯一性检查
在业务需要进行唯一性检查时,需要提供唯一性检查接口(一个接口可支持多个字段的检查)
GET /users/actions/uniqueCheck?userName=xxx
获取键值对数据
经常需要提供key,value类型的数据集合,以用户为例:
GET /users/kv
可支持参数查询
GET /users/kv?lastName=张三
GET /users/kv?queryKey=张三
可支持分页查询
GET /users/kv?pageNum=1&pageSize=50
数量查询
查询男性用户总数
GET /users/count?sex=1
分页与排序参数
- 分页(默认都分页)
GET /users?pageNum=1&pageSize=10
- 获取所有数据,不分页,可通过特定参数来表示不分页,都使用
/users
接口
GET /users?noPage=1
- 排序1(带下划线表示desc,不带表示默认的asc)
GET /users?sort=userName,_lastName
- 排序2(通过JSON格式字符串传递排序信息)
GET /users?sort={"userName":"desc", "lastName":"asc"}
更新资源单个属性
对于某些属性,产品设计时可以进行单独更新。
格式:PATCH /resources/{id}/:attribute?value=xxx
PATCH /users/1/mobile?value=135xxxxxxxx
Action 命名实践
上面是接口命名的实践,这里例举下Controller中Actions的实践。
还是以用户为例,但未使用 actions
.
操作 | Action Name | URI | HTTP Method |
---|---|---|---|
查询所有数据 | list | /users | GET |
创建单个资源 | create | /users | POST |
更新单个资源 | update | /users/1 | PUT |
删除单个资源 | delete | /users/1 | DELETE |
查询数量 | count | /users/count | GET |
键值对数据 | kv | /users/kv | GET |
批量查询 | batchQuery | /users/batchQuery | GET |
查询单个资源 | singleQuery | /users/singleQuery | GET |
唯一性检查 | uniqueCheck | /users/uniqueCheck | POST |
更新资源单个属性 | updateMobile | /users/1/mobile?value=135xxx | PATCH |
小结
良好且统一的接口命名规范,看上去是 赏心悦目 的,非常舒服。由于RESTful风格接口仅提供了基础的几种操作,因此技术团队需要进行拓展并规范下来。
无论以何种形式命名,能够使用统一的风格即可,本文仅起一个参考作用。
欢迎关注陈同学的公众号,一起学习,一起成长