陈同学
微服务
Accelerator
About
# RESTful API 实践 > [猪齿鱼 REST API 规范](https://choerodon.io/zh/docs/practice-specification-reference/development/developmen-to-micro-services/rest-api-specification/) 本文记录了 RESTful API 的一些实践经验,内容综合了部分 [后端圈.研习小组](https://www.yuque.com/server_mind_learn_group/aeq717/lvefcg) 关于 REST 的探讨结果,仅简单带一下理论知识,更多可参考: * [Roy Thomas Fielding](https://en.wikipedia.org/wiki/Roy_Fielding) 2000年的 [博士论文](http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm) 中 [Chapter 5: Representational State Transfer (REST)](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm) * [阮一峰:理解 RESTful 架构](http://www.ruanyifeng.com/blog/2011/09/restful.html) ## 简介 **REST** 是 **Representational State Transfer** 首字母缩写,翻译为 **表现层状态转化**,加上主语 **资源**,应为:**资源通过表现层进行状态转化**。 例如:服务端提供接口查询单个用户,返回数据格式可以是:JSON、XML、文本、HTML等,这就是资源的表现形式。客户端通过HTTP(HTTPS)协议传递某种格式(表现层)的数据给服务端来完成对资源的状态变更。 **技术团队理解并统一遵循 RESTful 接口的规范,可避免杂乱的接口定义,使得接口顾名思义,提高效率。** ## 接口组成 接口由HTTP动词、域名、版本、Endpoint组成。 ```http 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 就可以表示多种操作。 冻结用户 ```http PATCH /users/1/actions/freeze ``` 解冻用户 ```http PATCH /users/uniqueCheck ``` **注:团队内保持同一规范即可,也可不用actions,例如直接用 PATCH /users/1/freeze** ### 批量操作 * **批量查询** 根据用户ID批量检索用户 ```http GET /users/actions/batchQuery?userIds=1,2,3 ``` * **批量更新** 根据用户ID批量失效用户 ```http PATCH /users/actions/batchFreeze ``` ### 检索单个资源 除根据主键检索信息外,经常会根据其他唯一字段来检索数据。例如利用手机号、邮箱检索单个用户: ```http GET /users/actions/singleQuery?mobile=xxx GET /users/actions/singleQuery?mail=xxx ``` ### 唯一性检查 在业务需要进行唯一性检查时,需要提供唯一性检查接口(一个接口可支持多个字段的检查) ```http GET /users/actions/uniqueCheck?userName=xxx ``` ### 获取键值对数据 经常需要提供key,value类型的数据集合,以用户为例: ```HTTP GET /users/kv ``` 可支持参数查询 ```http GET /users/kv?lastName=张三 GET /users/kv?queryKey=张三 ``` 可支持分页查询 ```http GET /users/kv?pageNum=1&pageSize=50 ``` ### 数量查询 查询男性用户总数 ```http GET /users/count?sex=1 ``` ### 分页与排序参数 - 分页(默认都分页) ```http GET /users?pageNum=1&pageSize=10 ``` - 获取所有数据,不分页,可通过特定参数来表示不分页,都使用 `/users` 接口 ```http GET /users?noPage=1 ``` - 排序1(带下划线表示desc,不带表示默认的asc) ```http GET /users?sort=userName,_lastName ``` - 排序2(通过JSON格式字符串传递排序信息) ```http GET /users?sort={"userName":"desc", "lastName":"asc"} ``` ### 更新资源单个属性 对于某些属性,产品设计时可以进行单独更新。 格式:`PATCH /resources/{id}/:attribute?value=xxx` ```http 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风格接口仅提供了基础的几种操作,因此技术团队需要进行拓展并规范下来。 无论以何种形式命名,能够使用统一的风格即可,本文仅起一个参考作用。
本文由
cyj
创作,可自由转载、引用,但需署名作者且注明文章出处。
文章标题:
RESTful API 实践
文章链接:
https://chenyongjun.vip/articles/97
扫码或搜索 cyjrun 关注微信公众号, 结伴学习, 一起努力