大佬教程收集整理的这篇文章主要介绍了[接口设计]从客户端的角度设计后端的接口,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
一. 接口示例
接口描述:用户登陆成功后,或进入个人中心时会获取一次用户信息
URI | 方法 | @H_419_18@/userinfo | GET |
---|
请求参数
名称 | 必填 | 备注 | @H_419_18@ID | 是 | 用户ID |
---|
响应参数
名称 | 类型 | 备注 | @H_419_18@ID | String | 用户ID | @H_419_18@name | String | 姓名,例:张三 | @H_419_18@age | String | 年龄,例:20 |
---|
Json示例
{
"code":200,"msg":"成功","time":"1482213602000","data": {
"ID":"1001","name":"张三","age":"20"
}
}
二. 基本规范
1.通用请求参数
字段名称 | 说明 | @H_419_18@version | 客户端版本version,例:1.0.0 | @H_419_18@token | 登陆成功后,server返回的登陆令牌token | @H_419_18@os | 手机系统版本(Build.VERSION.RELEAS)例:4.4,4.5 | @H_419_18@from | 请求来源,例:androID/ios/h5 | @H_419_18@screen | 手机尺寸,例:1080*1920 | @H_419_18@ @H_402_16@model机型信息(Build.MODEL),例:Redmi Note 3 | @H_419_18@chAnnel | 渠道信息,例:com.wandoujia | @H_419_18@net | APP当前网络状态,例:wifi,mobile;部分接口可以根据用户当前的网络状态,下发不同数据策略,如:wifi则返回高清图,mobile情况则返回缩略图 | @H_419_18@appID | APP唯一标识,有的公司一套server服务多款APP时,需要区分开每个APP来源 |
---|
2.请求Path,http://www.online.com/api/ [path]
操作行为 | @H_867_10@methodPath | @H_419_18@查找 | GET | getXxx | @H_419_18@增加 | POST | addXxx/submitXxx | @H_419_18@修改 | POST | @H_402_16@modifyXxx @H_419_18@删除 | POST | delXxx |
---|
示例
操作行为 | @H_867_10@methodPath | @H_419_18@获取用户信息 | GET | getUserInfo | @H_419_18@增加收货地址 | POST | addAddress | @H_419_18@修改密码 | POST | @H_402_16@modifyPwd @H_419_18@删除收货地址 | POST | delAddress | @H_419_18@登陆 | GET | login | @H_419_18@发送短信验证码 | GET | sendSms | @H_419_18@订单支付 | POST | orderPay |
---|
3.响应数据
字段名称 | 说明 | @H_419_18@code | 响应状态码,200:成功;非200:失败 | @H_419_18@ @H_402_16@msg请求失败时的message | @H_419_18@time | 服务端时间戳,单位:毫秒。用于同步时间 | @H_419_18@data | 数据实体 |
---|
code=200时,msg=登陆成功/修改成功/提交成功;如果需要Toast,可以直接使用msg。
code!=200时,msg=错误提示信息;比如login接口,”账号或密码错误”,”账号不存在”类似这些的业务提示文案放在msg字段,客户端直接Toast就可以了。不过需要提醒后端同学,错误提示不能自己觉的什么合适就提示什么,要按需求文档来提供,或和PM确认。
// Json
{
"code":200,"data": {
"name":"张三","age":"20"
}
}
// model.java
public class Model {
public String name;
public String age;
}
// Json
{
"code":200,"data": {
"@R_419_6818@":["张三","李四"]
}
}
// model.java
public class Model {
public @R_419_6818@<String> @R_419_6818@;
}
请求参数
名称 | 必填 | 备注 | @H_419_18@pageNum | 是 | 当前第几页,例:1,2,3 | @H_419_18@pageSize | 是 | 每页条数,例:10 |
---|
响应数据
// Json
{
"code":200,"李四"],"@R_907_10586@l":"10"
}
}
// model.java
public class Model {
public @R_419_6818@<String> @R_419_6818@;
public String @R_907_10586@l;
}
4.命名规范
统一命名:与后端约定好即可(php和Js在命名时一般采用下划线风格,而Java中一般采用的是驼峰法),无绝对标准,不要同时存在驼峰”username”,下划线”phone_number”两种形式就可以了。
避免冗余字段:每次在新增接口字段时,注意是否已经存在同一个含义的字段,保持命名一致,不要同时存在”username”,”username”,”uname”多种同义字段。
注释清晰(重要):每个接口/字段都需要有详细的描述信息,很多时候接口体现业务逻辑,是团队中很重要的文档沉淀,同时,详细的接口文档,可以帮助新人快速熟悉业务。具体示例如下:
URI | 方法 | @H_419_18@/userinfo | GET |
---|
字段类型 | 字段名称 | 说明 | @H_419_18@Boolean | isVip | 是否时Vip用户,1:是,0:否 | @H_419_18@金额 | realPay | 订单实际付款金额,单位:元 | @H_419_18@时间 | payTime | 订单付款时间,单位:毫秒 | @H_419_18@日期 | payDate | 订单付款日期,格式”yyyy-MM-dd” | @H_419_18@状态 | status | 订单状态,1:进行中(payDate不返回),2:待支付(payDate返回),3:已支付(payDate不返回);(bool以1/0表示,状态从1+开始) |
---|
5.统一定义String字段类型
// Json
{
"name":"张三","isVip": true,"age":20,"money": 10.5
}
// Model.java
public class Model {
String name;
Boolean isVip;
int age;
float money;
}
{
//如果传true,false以外的数据,就会解析失败
"isVip": 20
"isVip":
}
解析报错:
(1)java.lang.IllegalStateException: Expected a Boolean but was numbER
(2)com.Google.gson.stream.MalformedJsonException: Unexpected value
{
"age": 20.5
"age": abc
"age": ""
"age":
}
解析报错:
(1)java.lang.numberFormatException: Expected an int but was 20.5
(2)java.lang.IllegalStateException: Expected an int but was StriNG
(3)java.lang.numberFormatException: empty String
(4)com.Google.gson.stream.MalformedJsonException: Expected value
{
"money": abc
"money": ""
}
解析报错:
(1)java.lang.numberFormatException: For input String: "abc"
(2)java.lang.numberFormatException: empty String
public class IntegerDefaultAdapter implements JsonDeserializer<Integer> {
@OverrIDe
public Integer deserialize(JsonElement Json,Type typeOfT,JsonDeserializationContext context)
throws JsonParseException {
// 如果Integer类型的字段,进行一次类型转换
try {
return Integer.parseInt(Json.getAsString());
} catch (numberFormatException E) {
}
return -1;
}
}
String Json = "{name:@R_419_6818@en,isVip:true,age:abc,money:1.0}";
Gson gson =
new GsonBuilder().registerTypeAdapter(int.class,new IntegerDefaultAdapter())
.create();
Model model = gson.fromJson(Json,Model.class);// age字段解析出来为-1
{
"name": "abc"
"name": "20"
"name": "10.2"
"name": "true"
}
优点:
注意事项:
Boolean类型数据,统一返回1(true)和0(false),客户端做一层容错判断,只有1才为true,其他非1,解析失败的情况均为false,例:
if(!TextUtils.isEmpty(isVip) && "1".equals(isVip)) {
return true;
}
return false;
status类型字段从1+开始,和Boolean类型(0否,1是)区分开。”0”的含义有2种,(1)非0即为真,所以0即表示false;(2)”0”是一种未赋值的默认状态。假设此时用0表示状态1,那么就很难判断出到底时数据解析失败,使用默认值0,还是说逻辑走通并赋值为0。例:orderstatus,1:进行中,2:待支付,3:已完成。
int,float类型数据,如果不是直接展示的话,需要做一次类型转换,注意捕获异常,在解析失败的情况下,使用default值。
int defaulTint = -1;
try {
defaulTint = Integer.parseInt(agE);
} catch (numberFormatException E) {
e.printstacktrace();
}
return defaulTint;
6.上传/下载接口,根据md5校验数据完整性
上传成功后,正常情况后端只需要返回code表示成功/失败,在开发阶段,可以让后端将上传成功后的图片url返回,这样当我们调用完接口以后,就可以通过该url字段查看图片是否上传成功,存储的尺寸大小,模糊度等,就不用每次粘着后端帮忙看请求结果了,这个思路同样通用于其他接口,不过上线后需要将这个不必要的字段去掉。
{
"code":200,"data": {
"url":"http://www.online.com/path/pic.jpg"
}
}
7.避免浮点型计算
8.Json数据保持良好结构
{
"userID"...
"username"...
"userPhoto"...
"orderID"...
"orderType"...
"addressID"...
"addressname"...
"addressDetail"...
}
{
"user":{
"ID"...
"name"...
"photo"...
}
"order":{
"ID"...
"type"...
}
"address":{
"ID"...
"name"...
"detail"...
}
}
三. 瘦客户端
客户端尽量只负责展示逻辑,不处理业务逻辑
客户端不处理金额的计算
客户端少处理请求参数的校验与约束提示
四.扩展性
文案与图片
数据列表化:尽量用@R_419_6818@(key,value)的数据格式定义类似列表的界面
方案1:客户端在写xml的时候将左侧的”姓名”,”性别”,”年龄”写死,右侧的具体数据从Json解析获得
{
"name": "张三","sex": "男","age": "20岁","nickname": "小张"
}
方案2(推荐):将左侧的title和右侧的value,以@R_419_6818@(key-value)的数据形式进行下发,优点:左,右侧文案灵活配置,后期如果需要扩展,新增或删除一个条目,都可以通过后端控制。不过采用这种形式,也需要考虑实际场景,对于变化不那么频繁,数据item较少,较固定的情况下其实没有必要设计的太灵活,只会增加开发成本。
{
"userInfos":[
{
"key":"姓名","value":"张三"
},{
"key":"性别","value":"男"
},{
"key":"年龄","value":"20岁"
},{
"key":"昵称","value":"小张"
}]
}
3.用flag替换Boolean:一般情况下,一款APP都会有config接口,用于获取一些常量文案,通用配置等信息,会有很多类似开关的字段,如:”isNew”,”isVip”,”isShowBalance”等等。
{
"isNew":"1",// 是否是新用户
"isVip":"1",// 是否是VIP用户
"isShowBalance":"1",//是否显示侧边栏余额模块
}
优化方案:通过二进制第1位表示”isNew”,二进制第2位表示”isVip”,二进制第3位表示”isShowBalance”。如果有其他新增状态,不需要新增字段,就需要改变返回的数据即可。
{
"flag":"7"// 二进制:111,表示3个状态都为true
"flag":"5"// 二进制:101,表示isNew,isShowBalance为true,isVip为false
}
long flag = 5;
System.out.println("bit=" + Long.toBinaryString(flag));
System.out.println("isNew=" + ((flag & 1) == 1));
System.out.println("isVip=" + ((flag & 2) == 2));
System.out.println("isShowBalance=" + ((flag & 4) == 4));
bit=101
isNew=true
isVip=false
isShowBalance=true
五.安全性
响应数据中包含用户隐私的字段数据,需要加*号。如:手机号,身份证,用户邮箱,支付账号,邮寄地址等。
{
"phone":"150*****000","IDCard":"3500**********0555","email":"40*****00@qq.com"
}
请求参数中包含用户隐私的字段参数,如:登陆接口的密码字段,需要进行加密传输,避免被代理捕捉请求后获取明文密码。
客户端和服务器通过约定的算法,对传递的参数值进行签名匹配,防止参数在请求过程中被抓取篡改。密钥记得放到so中,放在java层太不安全,so中要进行keystore反向签名校验,避免so被获取后直接调用获取算法。
六.兼容性
七.性能优化
无用字段清理
图片裁剪服务
局部刷新
wifi与移动网络的区别对待
八.体验优化
通过预加载降低对网络的依赖
{
"md5"... // 校验所有item的detail,只有在新订单,或订单完成后移除的情况下,md5才会变化
"order@R_419_6818@":[{
"ID"...
"status"...
"detail":{ // detail中尽量只保留变化情况较少的字段,避免md5频繁变化,如status就移出到item中存放
"type"...
"desc"...
}
},{
"ID"...
"status"...
"detail":{
"type"...
"desc"...
}
}]
}
转:http://blog.csdn.net/BaiHuaXiu123/article/details/54015240
以上是大佬教程为你收集整理的[接口设计]从客户端的角度设计后端的接口全部内容,希望文章能够帮你解决[接口设计]从客户端的角度设计后端的接口所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。