移动端接口开发规范

1.API命名规范

1.1 URL

提供给外部渠道使用(PC、app、H5、第三方合作平台)

  • app:/app/refund/create

  • 运营系统:/operation/refund/create

  • 商家端:/merchant/refund/create

  • 依次类推 xxx渠道:/xxx/controllerName/actionName

范例: https://api.weibo.com/2/friendships/friends.json

当前: http://192.168.0.130:16000/pipi-micro-server/pipi/friend/queryFriendData

1.2 参数命名

命名不规范导致无法通过参数名了解参数含义。

  • 使用准确的英文命名。
  • 使用驼峰命名法或下划线分隔

错误范例:

{
  "resultCode": "200",
  "resultMsg": "查询用户基本信息成功",
  "resultBody": {
    "user": {
      "userid": "e85f83b7e3cc40a585cce8831b9913e0",
      "level": "0",
      "birthday": null,
      "sex": null,
      "weight": null,
      "height": null,
      "telephone": "15855179814",
      "createtime": "2020-07-13 06:19:36",
      "petname": "路人丁",
      "professional": "理发师",
      "ppmoney": null,
      "area": "341222",
      "identity": "1",
      "heartrate": null,
      "powerrate": null,
      "disease": null,
      "emergencycontact": null,
      "emergencycontactnumber": null
    }
  }
}

2.错误信息返回

当前:

{
  "resultCode": "100",
  "resultMsg": "用户名或者密码错误,请重试!",
  "resultBody": null
}

当前行为是只要是错误就会返回100,成功则返回200。具体什么错误用resultMsg返回。

客户端需要做国际化,服务端返回为中文字段,有可能遇到乱码问题,二是如果国外使用返回的也是中文字段。对应不同的错误应该定义一套完整的错误码对应,resultMsg只是辅助,客户端可以通过错误码知道是何种错误,再使用用户选择的语言展示出来。

范例:

正常响应示例

{

    "status": 1,//状态值是1

    "error_code": 0,//同时错误代码是0表示无错误

    "message": "获取成功",//提示操作成功信息

    "data": []//主体返回内容

}

错误响应示例

{

    "status": 0,

    "error": 20102,//2:业务级错误(1代码系统级错误)固定一个字符;01:指的是01这个业务比如保洁 固定两个字符;02具体错误信息固定两个字符,会整理成一个对照表格,前端需要翻译成友好的提示

    "message": "用户id不能为空",//给前端程序员的不友好提示,指明错误的原因

    "data": {}  //data字段固定

}

3.效率

3.1面向对象的设计思想

Restful风格:RESTfu设计原则,它被RoyFelding提出(在他的”基于网络的软件架构”论文中第五章)。而REST的核心原则是将你的API拆分为逻辑上的资源。这些资源通过http被操作(GET,POST,PUT,DELETE)。但现在看,一般的操作只有两种:GET ,POST。

这个设计原则最简单的应用就是面向对象设计而不是页面来设计api。最开始的时候,app的一个页面需要什么数据,api就返回什么数据。结果随着app的UI不断改版,需要的数据不断变化,不停地修改api,最后当api的改动会影响以前的版本的时候,只能写一个新的api版本,最后弄得api中有很多version/2,version/3这样的标志,恶梦!

但根据object来设计,又有一个问题,一个大object可能包含很多小object,是一个api返回全部小object,还是分为多个api返回?根据业务和技术,带宽等仔细考虑吧。

目前我们的接口设计是根据业务来定制接口和返回,假设页面上只显示五个字段,那么后端就需要针对这个页面进行设计。

当然这这样的好处是显而易见的,在和客户端交互的过程中,传输的数据全是有用的数据,极大地节约了网络资源,而且只需请求一个接口,接口就返回了所有界面显示的数据,在弱网状态下,加快响应速度。

新浪微博的做法:打开个人中心,会分多次进行请求,’users/counts’批量获取用户的粉丝数、关注数、微博数,’users/domain_show’个性域名相关,’users/show’获取主要信息,这是比较极端的做法,仅供参考。

示例:

移动端接口开发规范_第1张图片

返回的数据结构如下

{

    "brand_name": "奥迪",

    "car_model": "SUV",

    "emission_standard": "国五",

    "car_owner": {

        "name ": "张三 ",

        "driving_years": "5年",

        "id": "666"

    }

}

其中车主是一个对象,车子是一个对象,两者是既有关系又相对独立。

总结建议是,新设计的接口,需要考虑到多端不同展示,尽可能的偏向于面向对象,少量特殊处理可以面向页面。当然,后端代码上,都是以对象的形式存在,逻辑必须清楚。

3.2 考虑移动端的网络情况和耗电量

对于移动APP开发者来说, 网络流量和电池电量是不得不考虑的问题。不过,您也许会说,这些跟接口没啥关系吧,服务器端的接口还能管得了客户端的网络流量和电量?

  1. 对于网络情况,接口应该具备为不同的网络提供不同的内容的能力, 通常,移动端的上网方式无非是2G(GSM、GPRS、EDGE)、3G(CDMA、TDSCDMA、WCDMA)、4G/5G、WIFI。设想一下,如果用户在流量需要花钱的情况下,你的app给用户展示了视频、音频、大量的图片和大量无用数据(接口中存在大量跟app页面无关的数据,俗称大而全的接口)。而没有通知用户的情况下用户会怎么想,毕竟国内的流量费用还是很贵的,应在不同的环境下提供不同的策略。

  2. 对于电量,app的哪些方面会消耗电量?比如app有大量的计算、有很炫的视觉画面都会消耗电量, 另外,不断的移动网络链接也会消耗大量的电量,我们都知道移动网络是通过无线电波来通讯的,那么发射装置就需要消耗一定的电量来发射和接收无线信号。特别的是,频繁的链接会不断的切换网络设备与移动基站之间连接状态,这都会消耗一部分电量。

所以,对于接口而言,尽量用少的链接传输多的数据,和尽量少的数据接收交互。

问题:3G/4G/5G时代需不需要考虑用户的流量成本? 对App的追求和定位到底是什么,只是满足功能需求,还是提供优质服务体验?

3.3 接口需不需要要为移动客户端考虑,做相应的API适配?

  • 一种声音是不需要,后端写一套接口,不管是web端,Android,ios,wap等都调用相同的接口,后端维护简单。
  • 另一种声音是需要,要依据不同场景,开发相应的API接口(如移动端,web端等)

相对于我目前而言第二种较为合理。提供一下例证,欢迎探讨。

​ 接口不仅仅是提供数据和功能就完事了,更应该充分考虑移动端的特性,为移动端提供更加方便、快捷的接口。

比如,在移动端里,下拉刷新和上拉加载更多是很常见的功能,如果接口仍然按照传统的web思路,

只提供按页读取的话,就会造成移动端的额外的数据请求和计算。 这时,接口就应该针对这两种类型的操作提供额外的支持。

再比如,对于一个新闻阅读类的app来说,最新的新闻列表里的文章,特别是前几条,用户很容易点击进去看,而后面的老的文章列表,一来用户下滑加载好几页的情况较少,二来过时的新闻用户也很少点。如果,接口在返回新闻列表时,对于最新的列表,可以直接把文章的正文(或者部分正文,比如一屏的内容)信息一起传给客户端,

这样,用户在打开新闻详情页的时候,就不用再从服务器端获取了,自然可以做到秒开。

比如访问第一页时,接口可以返回文章内容,如下所示 ,

content=1表示加载文章内容

newslist?page=1&pagesize=20&content=1

其他页时

newslist?page=5&pagesize=20&content=0 ,

不用加载文章内容。

当然,客户端要跟接口做好配合,搭配好,才能最大化的提高性能。

比如,移动端都有左右滑动来看上一篇、下一篇文章或者图片的功能,

如果,当用户请求某篇文章的时候,服务器端顺便也把下一篇文章的内容返回回来了,

那么当用户看下一篇的时候,是不是就很快了呢。

当然这种preload的方案也不能滥用,如果预加载数据的命中率较低的话,也不行,白白浪费了很多的流量。

3.4 APP接口设计构思应该思考的问题

  • 接口执行效率(接口访问速度)

    APP有别于WEB服务,对服务器端要求是比较严格的,在移动端有限的带宽条件下,要求接口响应速度要快,对数据要求也比较严格,app需要什么数据就传什么数据,不可多传,过多的数据量影响处理速度,最重要的是影响传输效率和浪费用户流量。接口要规范,以面向对象的思想设计接口。

易用性

  1. 接口、参数命名准确:无论是接口还是参数,命名都应该有意义,让人一目了然。(接口推荐根据APP效果图栏目进行命名)

  2. 一个页面尽可能就用一个接口: 现在很多的APP页面都有广告、焦点图、文章列表等,对于这些不同格式的数据,不可能都分配一个接口,这样加大了APP请求接口数,影响响应速度。建议服务器端尽可能处理好数据后通过一个接口返回给APP客户端,或把相似的部分功能合并已达到想要的效果,尽量不要出现一个页面七八上十个接口的情况。

  3. 接口数据、状态:接口必须提供明确的数据状态信息,不管是成功的,还是失败的,都必须返回给APP客户端,系统级异常,业务级异常,参数及异常都应有所体现。否则,接口的协议失去了所有的意义

  4. 接口要有可扩展性:方便后期功能性调整,接口应具备可扩展性,但扩展性也不能盲目不切实际的幻想可能会出现不同的数据逻辑。

  • 安全性

    1. 接口安全:目前一般都是在APP客户端和服务器通过约定的算法,对传递的参数值进行验证匹配。但是如果APP程序被反编译,这些约定的算法就会暴露,特别是在安卓APP中,有了算法,完全就可以通过验证模拟接口请求。或者引入jwt令牌(token)等解决方案。

    2. 加密规范:在传递用户名密码时,应采用规范的加密算法如MD5、RSA、DES,进行数据通信请求。

    3. https协议 :对于敏感的api接口,使用https协议 ,也是一种不错的选择,这也是一个趋势。https是在http超文本传输协议加入SSL层,它在网络间通信是加密的,所以需要加密证书。https协议需要ca证书,一般需要相应的费用成本。

API命名规则

其中一个原则,一看api名字就知道这个api是干啥。但是有个问题就是当你要负责几十甚至上百个api,你就知道不能”望名知api”是个什么样的痛苦。

就拿一个接口来举例吧

‘/User/userRedDot/version/1’

这是我们在使用的一个接口,从接口名字来看,不难看出User这个是用户相关的一个功能,然后userRedDot小驼峰命名指的是用户小红点,然后接口的版本号是第一版。以上4部分构成了一个完整的接口命名。

传参规则

接口文档中是会注明不同的接口该使用不同的传参方式

header参数部分:请求头部一般放入鉴权的相关参数,比如用户的token和签名,设备id,APP的标识,userAgent自定义等。

除去鉴权的参数,其他就是接口的入参传递(文档会注明传递方式):

  1. 一维参数 按照POST/GET按照普通的form-data和urlencode方式即可

  2. 多维参数 按照POST方式,并把body放入json的形式传递。

  3. 新增数据 POST

  4. 获取数据和修改数据用GET

兼容性原则

接口不可能永远不变,它会随着需求的变化而做出相应的变动,这种变动也可以理解为兼容或者不兼容。大部分情况下直接在这个接口上叠加版本号,并兼容旧版本。App的新版本开发传参时则将传入新版本的version。

接口的变化一般会有几种:

  1. 数据的变化,比如增加了旧版本不支持的数据类型(兼容:新增版本号,接口增量更新)

  2. 参数的变化,比如新增了参数(兼容:新增版本号,接口增量更新)

  3. 接口的废弃,不再使用该接口了(不兼容:原接口指定版本废弃,后端逻辑处理;原接口所有版本废弃,如果是业务流程修改,则停用原接口,并新开接口)

  4. 如果整个接口系统的根基都发生变动的话,比如微博API,从OAuth1.0升级到OAuth2.0,整个API都进行了升级,就无法兼容,只能进行版本强制升级了。

有时候,一个接口的变动还会影响到其他接口,但做的时候不一定能发现。

服务端异常处理

服务端的程序在运行的时候,可能因为一个数据的转化或空指针异常什么的,都不能让程序奔溃,需要捕获异常并对异常进行处理,并返回明确的数据状态信息,不管是成功的,还是失败的,都必须要有数据返回给APP客户端,否则,接口的协议失去了所有的意义

app客户端的语言 java和object-c都是强类型语言,所以怎么处理空值显得特别重要,不合理的设计很容易造成app的闪退。

从后台的角度来说,api中返回的数据中,正确值和空值的类型必须一样,举例,用户名的字段是“realname”: “xxx”,如果用户名为空,则应该返回“realname”:”“。如果返回值是一个array,空数据则返回一个空array,如果返回值是一个对象,空数据则返回一个空对象,绝对禁止null值。

对于客户端,必须用个全局的函数来处理所有api的返回数据,需要有一个机制:对于某个客户端需要数据,如果api中缺失,客户端自动补上并给予默认值。

同时,在数据库设计的时候,一个合理的设计必须是所有字段都有默认值,不应该允许null值。null在大量的语言和数据库中,会带来无穷的问题。

如果服务端是php,还有一个问题,php中数组和字典都是array,但是可以用(object)[]返回对象,但在java和object-c中是不一样,这个问题一定要注意。

补充说明下json的六种数据类型数据类型和约定

Number:整数或浮点数

String:字符串

Boolean:true 或 false

Array:数组包含在方括号[]中

Object:对象包含在大括号{}中

Null:空类型

前后端需要对数据类型进行约定:

- 时间日期型数据:直接返回格式化后的时间字符串或者直接返回时间戳

- 数字类型和文本类型:统一使用字符串格式

- 布尔值类型:统一使用字符串’0’和’1’来表示假和真

- 不返回Null类型数据

你可能感兴趣的:(Android,笔记)