做者:邵磊html
juejin.im/post/59eafab36fb9a045076eccc3前端
随着互联网高速发展,公司对项目开发周期不断缩短,咱们面对各类需求,使用原有对接方式,各端已经很难快速应对各类需求,更难以提升效率。因而,咱们不得不从新制定对接规范、开发逻辑以便快速上线项目。html5
尽量的缩小沟通的成本,开最少的会,肯定大部分的事。java
花最少的时间写文档,保证90%的开发人员看懂全部内容。ios
哪怕不看文档,也能知道各类接口逻辑。angularjs
不重复写代码web
尽量的写高可读性的代码面试
完成了先后端分离数据库
Android、ios、web共用一套接口编程
统一接口规范(post、put、get、patch、delete)
统一了调试工具
统一了接口文档
接口是这样子的:
客户端请求是这样的:
…/A项目/模块1/getProducts?id=1&a=2&b=3&c=4&d=5…………
A页面=====》B页面(携带n个变量)====》C页面(携带m个变量,包含i个A页面的变量) -------常常n>4
大部分请求是POST,至于put、patch、delete是什么鬼,关我屁事。
关于接口入参使用json,那彻底是看开发心情。
出参是这样的:
{"message":"success","code":0,"data":具体内容}
其中data里包含数组多是[{"a":"1","b":"1"},{"a":"1","b":"1"},{"a":"1","b":"1"},{"a":"1","b":"1"}]即便下一个页面用到也不会使用id,而是把全部字段都传进去。A接口中,返回产品用product;B接口中使用good,多个接口极可能不统一。
客户端对接是这样子的:
安卓、ios一套;部分接口各自用一套;html5端一套。
客户端和后台是不停交流的
接口文档是这样的
swagger
阿里的rap
Word文档
其它
固然了,我以为swagger和rap神器都是很是强大的,可以实现各类功能逻辑,可是考虑到开发人员掌握程度不通,复杂度较高,难以提升效率,我决定初期并不使用这两样神器。
后端是这样的
…/A项目/模块1/getProducts ----接口
…/A项目/模块1/Products.html ----页面
…/A项目/模块1/Products.js ----静态资源
接口和静态资源缠在一块,毕竟不少页面多是一位开发人员同时开发前端、后端,这里的弊端是,只须要本身清楚逻辑,不少作法临时应付,方案并不优雅,别人也很难看懂。一旦这位同事离职,不少说不清的逻辑就留给后人采坑了。
等等…………
下面步入正题,面对以上众多问题聊聊我是如何从新制定流程的
约定数据库里全部表必须包含名为id主键字段。可能有人会说,正常来讲不是每张表里都应该有id主键吗?可是,咱们项目中因为以前开发不严谨,部分表没有id主键,或者不为id的主键。这里咱们采用分布式的全球惟一码来做为id。
约定全部出参里含list,且其余请求会用到这组list,则list里全部对象必须含id惟一标识。
约定token身份认证统一传入参数模式,后端采用aop切面编程识别用户身份。其余参数一概为json。
首先咱们选择一个名词复数,好比产品
post方法
新增一条XXX
好比 ……/products
则表明新增一条产品入参json以下:
{
"name":"我是一款新产品",
"price":100,
"kind":"个人分类",
"pic":[一组图片],
//等等还有不少
}
java 代码control层
@ResponseBody
@RequestMapping(value = "/A项目/B模块/products", method = {RequestMethod.POST})
public ResultObject getProducts() {
//具体逻辑。
}
put方法
新增某条XXX记录
好比 ……/products/1111111111
入参json以下:
{
"name":"我是一款新产品",
"price":100,
"kind":"个人分类",
"pic":[一组图片],
//等等还有不少
}
表示增长一条1111111111id的记录
java代码control层
@ResponseBody
@RequestMapping(value = "/A项目/B模块/products/{id}", method = {RequestMethod.PUT})
public ResultObject putProducts(@PathVariable(value = "id") String id) {
//具体逻辑。
}
get方法
得到全部XXX
……/products 则表明获取全部产品
由于有分页,因此咱们后面加了?page=1&pageSize=50
咱们约定了全部名词复数,都会返回list,且list每一个对象都有字段为id的惟一id。
好比
{
"data":{"list":[{"id":"惟一id","其余不少字段":""},{"id":"惟一id","其余不少字段":""}],"page":1,其余字段},
"code":0,
"message":"成功"
}
……/products/{id} 获取某个具体产品(必定比列表更详细)
好比某个具体产品里还包含一个list,如该产品推荐列表,则:……/products/{id}/recommendations
假设它包含的不是一个list,而是对象,好比产品佣金信息,则:……/products/{id}/Commission
这里咱们以是否名词复数来判断是对象仍是list.
java代码control层
@ResponseBody
@RequestMapping(value = "/A项目/B模块/products/{id}", method = {RequestMethod.GET})
public ResultObject putProducts(@PathVariable(value = "id") String id) {
//具体逻辑。
}
patch 方法
更新局部XXX产品YYY信息
入参是post方法时入参的子集,全部支持更新的参数会说明,并非支持全部变量
……/products/{id}
{
"name":"我是一款新产品",
"price":100,
//部分变量
}
java代码control层
@ResponseBody
@RequestMapping(value = "/A项目/B模块/products/{id}", method = {RequestMethod.PATCH})
public ResultObject putProducts(@PathVariable(value = "id") String id) {
//具体逻辑。
}
delete方法
删除XXX记录
……/products/11111
删除11111产品。
java代码control层
@ResponseBody
@RequestMapping(value = "/A项目/B模块/products/{id}", method = {RequestMethod.DELETE})
public ResultObject putProducts(@PathVariable(value = "id") String id) {
//具体逻辑。
}
其余说明
咱们尽量少的使用动词,但有一些行为须要使用动词,好比登陆等。关于版本号,咱们打算在模块后增长/v1/等标识。
服务端要对用户角色进行判断,是否有权限执行某个逻辑。
后端以开发接口为主,再也不参与页面开发,或者混合式jsp页面开发,统一以接口形式返回,前端经过js渲染数据以及处理逻辑。
web、Android、ios使用统一接口,不在由于哪方特殊要求额外开放接口。
基于mybatis-generator改形成适合咱们项目的dao层以及部分service层,内部共同维护共同使用。
虽然有上文中介绍的rap和swagger都是特别牛的接口神器,可是咱们仍是选择了postman,开发人员将接口名称、说明、入参、出参,以及各类出参示例都存储,这样开发直接能够看得清接口含义。
咱们建议使用浏览器插件,这里以360极速浏览器为例。插件下载地址:
https://download.csdn.net/download/qq273681448/10033456
打开360浏览器扩展中心,而后勾选开发者模式,再点击加载已解压的扩展程序,选中压缩包解压后的目录,最后点击运行便可。
其中出参注释、及接口说明,写在tests里:
/*
这里是接口说明,和每一个出参、入参的意思。
*/
接口按模块划分为文件夹:
入参:
出参示例:
正常请求:
开发人员便可直接看到接口示例进行开发,而开发人员开发的时候,本身调用一次便可保存为postman文件,为了加快上线,咱们容许将java中实体类变量定义的代码(含注释)直接复制粘贴出来。
从短时间角度上讲,个人要求是减小js文件的变动,若是有变动,务必更改版本号。那么如何减小修改,咱们的作法是将一部分js写在html内,反正先后端分离,大不了刷新一下cdn的节点缓存,毕竟大部分浏览器也不会主动缓存html文件(大部分浏览器会缓存js等文件)。
这里咱们使用angular js的请求框架,由于咱们内部对angularjs使用较多,比较熟悉,封装后的请求,能够自动弹窗错误请求,可复写错误回调。
目前,咱们客户端看到接口,大概能说出其意思,也能猜出一连串接口的含义,好比
……/classes
能够看出它是获取班级列表接口,
猜到
……/classes/id get获取id为id的班级详情
……/classes/id patch 修改班级信息
……/classes/id delete 删除班级信息
至于入参,patch是post的子集、put=patch、delete无入参。
而入参含义,直接打开postman能够直接查看每一个字段的含义,而且,能够实时调取开发环境数据(非开发人员电脑),这里咱们使用了多环境,详情可了解:
https://juejin.im/post/59e1d92d51882578db27c2e1
前端使用统一封装后的js请求框架也加快了开发进度,不用造轮子。
开发人员,通常代码开发写好,使用postman自我测试,测试完成后,接口文档也就写好了。
测试人员想了解接口文档的也能够直接使用postman进行导入查看。
至此,咱们交流成本降低了一大半,剩下开会的内容就是按ui分解需求或者按ui施工了。
通过一番的折腾,开发进度总算快了点,也必定程度上达到了快速上线项目的效果。关于restful风格api,每一个人都有本身的看法,只要内部约定清楚,能尽量少的减小沟通,我以为就是好的理解。至于接口工具,可能不少人会说为何不用以前的,我以为之后仍是会用的,最好能作到插件自动化生成api,可是对java开发注释要求比较严格,随意慢慢来吧,毕竟后面咱们还有不少路要走。
推荐阅读(点击便可跳转阅读)
2. 面试题内容聚合
3. 设计模式内容聚合
4. Mybatis内容聚合
5. 多线程内容聚合