前后端对接规范

什么是规范

约定俗成的标准

目的:

  1. 提高了开发效率,降低了沟通成本,减少不必要的扯皮;
  2. 缩短联调时间,减少联调阶段的代码调整,保证开发效率;
  3. 减少测试阶段排查问题的归属,加快测试进度,保证质量;
  4. 易于故障排除和在线修复。

协作流程规范:

  1. 需求确认。对于产品提出需求,涉及的各方包括产品、前端、后端、测试和UED。就需求的认知达成一致是开发的第一步。
  2. 接口设计。前后端对接接口:后端提供接口,前后端在接口的设计上要达成一个大方向。
    正常前端后端都可以来设计接口,我们公司当前后端设计接口,但是前端需要知道知道什么接口
  3. 技术方案评审:开发前进行技术方案评审,确保各方对需求有统一认识,双方重新确认接口领域的可行性。
  4. 并行开发,前后端自测:前后端并行开发。在这个阶段,前端可以模拟数据进行页面渲染。
  5. 开发环境联调:前后端自测完成后,在开发环境上完成接口联调。

流程图:

image

版本

应该将API的版本号放入URL。

https://api.example.com/v1/

路径

在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表格名对应。一般来说,数据库中的表都是同种记录的"集合"(collection),所以API中的名词也应该使用复数。

https://api.example.com/v1/zoos
https://api.example.com/v1/animals
https://api.example.com/v1/employees

HTTP动词

对于资源的具体操作类型,由HTTP动词表示。

常用的HTTP动词有下面五个(括号里是对应的SQL命令)。

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

举行个粟子

GET /zoos:列出所有动物园
POST /zoos:新建一个动物园
GET /zoos/ID:获取某个指定动物园的信息
PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
DELETE /zoos/ID:删除某个动物园
GET /zoos/ID/animals:列出某个指定动物园的所有动物
DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物

过滤

如果记录数量很多,服务器不可能都将它们返回给用户。API应该提供参数,过滤返回结果

?limit=10:指定返回记录的数量
?offset=10:指定返回记录的开始位置。
?page=2&per_page=100:指定第几页,以及每页的记录数。
?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
?animal_type_id=1:指定筛选条件

返回结果数据

针对不同操作,服务器向用户返回的结果应该符合以下规范。

GET /collection:返回资源对象的列表(数组)
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回完整的资源对象
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档

分页

返回资源集合是,包含与分页有关的数据如下

{
  "page": 1,            # 当前是第几页
  "pages": 3,           # 总共多少页
  "page_size": 10,       # 每页多少数据
  "has_next": true,     # 是否有下一页数据
  "has_prev": false,    # 是否有前一页数据
  "total": 27           # 总共多少数据
}

接口返回的数据结构和状态码

data:业务数据

code:状态码

msg:状态信息。这里是给用户提示的信息。如果需要增加详细错误信息。把msg拆成一个对象{}

{
    "code": ok,
    "data":[],
    "message": {
        "text": "参数错误",
        "parameters": {
            "email": "电子邮件格式不正确"
        }
    }
}

提供一套统一的错误码规范, 协助多方人员来排查出接口的错误

用户发现错误, 可以截错误码的图, 就能够提供有效的信息帮助开发人员排查错误

测试人员发现错误, 可以通过错误码, 快速定位是前端的问题还是后端接口的问题

                                                       发送 HTTP 请求
                                                 ┌───────────┴───────────┐
                                              发送成功¹               发送失败²
                                                 │                       │
                                      ┌──────────┴──────────┐            A 例如: A100
                                获得 HTTP 响应       无法获得 HTTP 响应³
                                      │                     │
                                 HTTP status                A 例如: A200
                           ┌──────────┴──────────┐
                       HTTP 成功(200-300)     HTTP 异常
                           │                     |
               {data, status, statusInfo}        H${HTTP status} 例如: H404
               ┌───────────┴───────────┐
          接口调用成功(status:0)   接口调用失败
      ┌────────┴────────┐              |
客户端处理出错      客户端处理正常       B${status}${statusInfo.message} 例如: B100
      |
      C 例如: C100

接口传参注意事项:

  • 接口实现的大方向遵循 RESTful 风格
  • 接口返回的数据结构统一,业务数据,状态码,状态信息
  • 统一错误提示
  • 前后端数据列表相关接口,如果返回为空则返回空数组[] 或空集合{} ,减少前端很多琐碎的空值判断,特殊情况的特殊分析
  • 调用接口业务失败的常用错误码,未授权,未登录等
  • 图片是否全路径,哪端都合适
  • 时间字段建议同时返回时间戳的原始值(或 ISO 标准格式)和用于统一显示的格式化文本
    • 例如: {"createTime": 1543195480357, "createTimeText": "2018年11月26日"}
  • 大数字返回给前端用字符串类型,防止js溢出
  • 逻辑复杂的判断放到后端处理,前端尽量减少现场判断。IF条件多于2个则视为逻辑复杂。
  • 后端做好数据整合,避免前端数据重组,树的数据不大,全量返回,数据量大则异步返回
  • 不同设备端的接口分开,不共用接口
  • 计算型的数据,前端展示实时计算。后端入库后端自行计算
  • 接口只展示页面需要用到的字段,不展示多余无用字段
  • 控制前端显示逻辑判断放在后端处理,前端尽量减少现场判断。按钮是否展示或禁用通过两个及以上状态判断的,需要后台返回一个新的状态值,只能通过一个状态判断
  • 渲染逻辑禁止跨多个接口调用;

以免出现前后端分离之后最容易出现的扯皮现象. 特别是当你碰到做事不主动(无责任感)的后端, 什么都要前端来催. 比如什么接口又缺了一个字段没有提供啦, 什么又少了一个接口啦, 等等诸如此类. 后端不去熟悉业务, 也不看界面原型和需求, 只管把接口做完, 任务完成就万事大吉了, 每天除了等前端通知哪里要修改, 自己就像没事人一样.