I. 网络API接口设计

手机App以及使用了Ajax技术或做了前后端分离的页面都需要通过网络API(Application Programming Interface)和后台进行交互,所谓API,指的应用程序的编程接口;而网络API通畅指的是基于HTTP或HTTPS协议的一个URL(统一资源定位符),通过这个URL我们可以让服务器对某个资源进行操作并返回操作的结果。基于HTTP(S)协议最大的好处就在于访问起来非常的简单方便,而且没有编程语言和应用环境上的差别。

设计原则

关键问题

为移动端或者PC端设计网络API接口一个非常重要的原则是:根据业务实体而不是用户界面或操作来设计。如果API接口的设计是根据用户的操作或者界面上的功能设置来设计,随着需求的变更,用户界面也会进行调整,需要的数据也在发生变化,那么后端开发者就要不停的调整API,或者给一个API设计出多个版本,这些都会使项目的开发和维护成本增加。

下面是某个网站开放API的接口,可以看出API的设计是围绕业务实体来进行的,而且都做到了“见名知意”。

评论
comments/show获取某条微博的评论列表
comments/by_me自己的评论列表
comments/to_me收到的评论列表
comments/mentions@了自己的评论列表
comments/create创建一条评论
comments/destroy删除一条评论
comments/reply回复一条评论

注意:上面的API接口并不是REST风格的,关于REST的知识,可以阅读阮一峰老师的《理解RESTful架构》以及《RESTful API设计指南》

API接口返回的数据通常都是JSON或XML格式,我们这里不讨论后者。对于JSON格式的数据,我们需要做到不要返回null这的值,因为这样的值一旦处置失当,会给移动端的开发带来麻烦(移动端可能使用强类型语言)。要解决这个问题可以从源头入手,在设计数据库的时候,尽量给每个字段都加上“not null”约束或者设置合理的默认值约束。

其他问题

  1. 更新提示问题:设计一个每次使用系统首先要访问的API,该API会向移动端返回系统更新的相关信息,这样就可以提升用户更新App了。
  2. 版本升级问题:API版本升级时应该考虑对低版本的兼容,同时要让新版本和旧版本都能够被访问,可以在URL中包含版本信息或者在将版本号放在HTTP(S)协议头部,关于这个问题有很多的争论,有兴趣的可以看看stack overflow上面对这个问题的讨论。
  3. 图片尺寸问题:移动端对于一张图片可能需要不同的尺寸,可以在获取图片时传入尺寸参数并获取对应的资源;更好的做法是直接使用云存储或CDN(直接提供了图片缩放的功能),这样可以加速对资源的访问。

文档撰写

下面以设计评论接口为例,简单说明接口文档应该如何撰写。

评论接口

​​‌‌​​​‌‌​‌​​‌‌‍​‌​‌‌‌​​‌‌‌‌​‌​‍​‌​​‌​​​‌​​​‌‌​‍​‌​‌‌​​​‌‌​​​​​‍​​‌​‌‌‌‌‌‌‌‌​​​‍​‌‌​​‌‌‌​‌‌​​‌‌‌‍​‌‌​​​‌‌‌​​​‌​‌‍​​‌‌‌‌‌‌‌‌​​‌‌‍‌​​​‌‌‌‌‍‌​​​​‌‌​‍‌​​​‌​‌‌‍‌​​‌​‌‌‌‍‌​​‌​​​​‍‌​​‌​​​‌‍​‌‌​​‌‌‌‌​​​​‌‌​‍​​​‌​​‌​​​‌​​​‌‍​‌​​​​​‌‌‌‌‌‌‌‌‍​‌​‌‌​​​​‌​‌‌‌​‍​‌‌​​​‌‌​‌‌​‌​​‍‌‌​‌​​‌​‍​​​​​​​‌​‌​‌‌‌​‍​​​​​​‌​​‌​​​‌‌‍‌​‌‌‌‌‌​‍‌​‌​‌‌‌‌‍‌​‌‌​‌‌​‍​​‌‌‌​​​‌​‌‌​‌​‍​‌​‌‌​​​​​‌‌‌​​‍​‌‌‌​‌​​​‌​​​​​‌‍​‌‌‌​‌​​​‌​‌‌‌‌​‍​​‌‌‌‌‌‌‌‌​​‌​‍​​​​​​​​‌‌‌‌​​‌‌‍​​​‌​‌​‌‌​​‌‌‌​‍‌​​​‌​‌‌‍‌​​‌​​​​‍‌​​‌​​​‌‍‌​​​​‌‌​‍​‌‌​​​‌​‌‌‌​​​‌‍‌‌​​‌‌​‌‍‌‌​​‌‌‌‌‍‌‌​​‌‌​‌‍‌‌​​‌‌‌‌‍‌‌​‌​​‌​‍‌‌​​‌‌‌‌‍‌‌​​​‌‌‌‍‌‌​‌​​‌​‍‌‌​​‌‌‌‌‍‌‌​​‌‌​​‍​‌​‌‌​‌‌‌‌​​‌​​‍​‌‌​​​​‌​‌​​​‌‌‍​​​​​​​​‌‌‌‌​​‌‌‍​‌​‌‌​​​‌‌​​​​​‍​​‌‌​‌​​‌‌‌‌​​​‍​‌​‌​​​‌‌​​‌‌‌‌‍​‌​‌​​​‌​‌‌‌‌‌‌‍​​​​​​​​‌‌‌​​‌​‌‍‌​​‌​‌‌‌‍‌​​​‌​‌‌‍‌​​​‌​‌‌‍‌​​​‌‌‌‌‍‌‌​​​‌​‌‍‌​‌​​​‌‌‍‌​‌​​​‌‌‍‌​​​‌‌​‌‍‌​​‌​​​​‍‌​​​‌​​​‍‌​​​‌‌​​‍‌​​‌‌​‌​‍‌​​‌‌‌‌​‍‌‌​‌​​​‌‍‌​​‌‌‌​​‍‌​​‌​​​​‍‌​​‌​​‌​‍‌​‌​​​‌‌‍‌​​‌​​‌‌‍‌​​‌​‌‌​‍‌​​‌​​​‌‍‌​​​‌​‌​‍‌​​​​‌‌‌‍‌​‌​​​‌‌‍‌​​​‌‌‌‌‍‌​​​​‌‌​‍‌​​​‌​‌‌‍‌​​‌​‌‌‌‍‌​​‌​​​​‍‌​​‌​​​‌‍‌​​​​‌‌‌‍‌​​‌​‌‌​‍‌​​‌‌‌‌​‍‌​​‌​​​‌‍‌​​‌‌​​​‍‌‌​‌​​‌​‍‌​​‌​​‌​‍‌​​​‌​‌​‍‌‌​‌​​‌​‍‌​​‌​‌​​‍‌​​‌‌‌‌​‍‌​​‌​‌‌​‍‌‌​‌​​‌​‍‌​​‌‌​​‌‍‌​​‌‌‌‌​‍‌‌​‌​​‌​‍‌​​​​‌​‌‍‌​​‌​‌‌‌‍‌​​‌​‌‌​‍‌‌​‌​​‌​‍‌​​​‌​​​‍‌​​‌‌‌‌​‍‌​​‌​​​‌‍‌​​‌‌​​​‍‌‌​‌​​‌​‍‌​​‌​​‌‌‍‌​​​‌​‌​‍‌​​‌​​​​‍‌‌​‌​​‌​‍‌​​‌‌‌‌​‍‌​​​‌‌‌‌‍‌​​‌​‌‌​‍‌​​‌​‌​‌‍‌​​‌​‌‌​‍‌​​‌‌​‌​‍‌‌​‌​​‌​‍‌​​‌​‌​​‍‌​​‌​​​​‍‌​​​‌​‌​‍‌‌​‌​​‌​‍‌​​​‌‌​​‍‌​​‌​‌‌‌‍‌​​‌‌​‌​‍‌‌​‌​​‌​‍‌​​‌​‌​‌‍‌​​‌​‌‌​‍‌‌​‌​​​‌‍‌​​‌​‌‌‌‍‌​​​‌​‌‌‍‌​​‌​​‌​‍‌​​‌​​‌‌

全局返回状态码

返回码返回信息说明
10000获取评论成功
10001创建评论成功
10002无法创建评论创建评论时因违反审核机制而无法创建
10003评论已被删除查看评论时评论因不和谐因素已被删除
10004…………
  1. GET /articles/{article-id}/comments/

开发者:王大锤

最后更新时间:2018年8月10日

标签:v 1.0

接口说明:获取指定文章的所有评论

使用帮助:默认返回20条数据,需要在请求头中设置身份标识(key)

请求参数:

| 参数名 | 类型 | 是否必填 | 参数位置 | 说明 |
| ------ | ------ | -------- | -------- | ------------------------------------ |
| page | 整数 | 否 | 查询参数 | 页码,默认值1 |
| size | 整数 | 否 | 查询参数 | 每次获取评论数量(10~100),默认值20 |
| key | 字符串 | 是 | 请求头 | 用户的身份标识 |

响应信息:

{
    "code": 10000,
    "message": "获取评论成功",
    "page": 1,
    "size": 10,
    "totalPage": 35,
    "contents": [
        {
            "userId": 1700095,
            "nickname": "王大锤",
            "pubDate": "2018年7月31日",
            "content": "小编是不是有病呀",
            /* ... */
        },
        {
            "userId", 1995322,
            "nickname": "白元芳",
            "pubDate": "2018年8月2日",
            "content": "楼上说得好",
            /* ... */
        }
    ]
    /* ... */
}
  1. POST /articles/{article-id}/comments

开发者:王大锤

最后更新时间:2018年8月10日

标签:v 1.0

接口说明:为指定的文章创建评论

使用帮助:暂无

请求参数:

| 参数名 | 类型 | 是否必填 | 参数位置 | 说明 |
| ------- | ------ | -------- | -------- | ---------- |
| userId | 字符串 | 是 | 消息体 | 用户ID |
| key | 字符串 | 是 | 请求头 | 用户的令牌 |
| content | 字符串 | 是 | 消息体 | 评论的内容 |

响应信息:

{
    "code": 10001,
    "message": "创建评论成功",
    "comment": {
        "pubDate": "2018年7月31日",
        "content": "小编是不是有病呀"
        /* ... */
    }
    /* ... */
}