API规约

概述

所有软件的UI功能都依赖于后端的API能力输出,规范的API设计以及版本管理对软件功能交付的质量与效率都至关重要。

说明:这里的API是指Restful API

设计原则

API根URL

如果预期系统非常庞大,则建议尽量将API部署到独立专用子域名(例如:“api.”)下;如果确定API很简单,不会进一步扩展,则可以考虑放到应用根域名下面(例如,“/api/”)。

  独立子域名:https://api.example.com/api/v1/*
  共享应用根域名:https://example.org/[xxx]/api/v1/* (微服务平台一般都是通过网关的统一域名对外)

API各模块URL

建议每个领域或者Controller统一一个URL根,一般的形式是:/api/v1/[xxx],xxx表示某个领域模块名称

URI末尾不要添加“/”

多一个斜杠,语义完全不同,究竟是目录,还是资源,还是不确定而多做一次301跳转?尽量保持URI结构简洁、语义清晰。

  负面case:http://api.canvas.com/api/v1/shapes/
  正面case:http://api.canvas.com/api/v1/shapes

禁止在URL中使用“_”

目的是提高可读性,“”可能被文本查看器中的下划线特效遮蔽。建议使用连字符“-”替代下划线“”,使用“-”提高URI的可读性。

  负面case:http://api.example.com/api/v1/blogs/my_first_post
  正面case:http://api.example.com/api/v1/blogs/my-first-post

禁止使用大写字母

RFC 3986中规定URI区分大小写,但别用大写字母来为难程序员了,既不美观,又麻烦,同样的原则:建议使用连字符“-”连接不同单词。

  负面case:http://api.example.com/api/v1/My-Folder/My-Doc
  正面case:http://api.example.com/api/v1/my-folder/my-doc

不要在URI中包含扩展名

应鼓励REST API客户端使用HTTP提供的格式选择机制Accept request header。

  负面case:http://api.example.com/api/v1/my-doc/hello.json
  正面case:http://api.example.com/api/v1/my-doc/hello

建议URI中的名称使用复数

为了保持URI格式简洁统一,资源在URI中应统一使用复数形式,如需访问资源的一个实例,可以通过资源ID定位(@PathVariable)。

  负面case:http://api.college.com/api/v1/student/3248234
  正面case:http://api.college.com/api/v1/students/3248234

如何处理关联关系?

  http://api.college.com/api/v1/students/3248234/courses - 检索学生3248234所学习的所有课程
  http://api.college.com/api/v1/students/3248234/courses/physics - 检索学生3248234的所学习的物理课程

建议URI设计时只包含名词

每个URI代表一种资源或者资源集合,因此,建议只包含名词,不包含动词。

  负面case:http://api.example.com/api/v1/get-all-employees
  正面case:http://api.example.com/api/v1/employees

那么,如何告诉服务器端我们需要进行什么样的操作?CRUD?

答案是由HTTP动词表示。

  GET(SELECT):从服务器取出资源(一项或多项)。
  POST(CREATE):在服务器新建一个资源。
  PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
  PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
  DELETE(DELETE):从服务器删除资源。

禁止由第三方开发人员任意指定约束条件

非常重要的一点:禁止让第三方开发人员自己任意指定排序过滤器、返回结果集的约束条件。强烈建议服务器端设置默认单页数量,如果无限制,很可能造成服务器资源及网络资源过度消耗,响应缓慢,网络丢包等异常情况。

版本管理

整体建议

  • 建议通过URI指定服务版本,版本采用字符“v”+数字主版本号,例如,/v1/xxxs

  • 建议版本控制在资源层面,也即Controller维度

    服务后端分包建议规则如下:

    Domain: com.xxx.[user].domain.entity
    Api:
    com.xxx.api.[user].controller.v1
    com.xxx.api.[user].controller.v2
    
  • API升级建议

    • 尽量做兼容性设计,不要随便升级版本

    • 升级可分步实施,达到最终整个资源整体升级的目的,不同版本相互独立,便于后续拆分独立部署、独立维护等(可能存在代码重复,尽可能抽象通用服务或方法)

    • 先将资源的部分方法升级至高版本,并进行灰度发布,例如,/v1/users/check升级至 /v2/users/check,其他API版本维持v1不变

    • 升级资源的所有方法至高版本,并发布公告,要求客户限期升级API

    • 停止旧版本服务

URL中指定版本

  • URI上添加版本号:例如,https://api.example.org/api/v1/users

  • 参数中添加版本号: 例如,https://api.example.org/api/users?v=1.0

好处:

  • 直接可以在URI中直观的看到API版本;
  • 可以直接在浏览器中查看各个版本API的结果;

坏处:

  • 版本号在URI中破坏了REST的HATEOAS(hypermedia as the engine of application state)规则。版本号和资源之间并无直接关系。

接口注释

Swagger注释描述,要求使用OpenAPI规范注释接口

参考文章

《汉得开放平台文档》