隨着互聯網高速發展,公司對項目開發週期不斷縮短,咱們面對各類需求,使用原有對接方式,各端已經很難快速應對各類需求,更難以提升效率。因而,咱們不得不從新制定對接規範、開發邏輯以便快速上線項目。html
儘量的縮小溝通的成本,開最少的會,肯定大部分的事。前端
花最少的時間寫文檔,保證90%的開發人員看懂全部內容。html5
哪怕不看文檔,也能知道各類接口邏輯。java
不重複寫代碼ios
儘量的寫高可讀性的代碼angularjs
完成了先後端分離web
Android、ios、web共用一套接口數據庫
統一接口規範(post、put、get、patch、delete)編程
統一了調試工具json
統一了接口文檔
接口是這樣子的:
客戶端請求是這樣的:
…/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能夠直接查看每一個字段的含義,而且,能夠實時調取開發環境數據(非開發人員電腦),這裏咱們使用了多環境,詳情可瞭解:
前端使用統一封裝後的js請求框架也加快了開發進度,不用造輪子。
開發人員,通常代碼開發寫好,使用postman自我測試,測試完成後,接口文檔也就寫好了。
測試人員想了解接口文檔的也能夠直接使用postman進行導入查看。
至此,咱們交流成本降低了一大半,剩下開會的內容就是按ui分解需求或者按ui施工了。
通過一番的折騰,開發進度總算快了點,也必定程度上達到了快速上線項目的效果。關於restful風格api,每一個人都有本身的看法,只要內部約定清楚,能儘量少的減小溝通,我以爲就是好的理解。至於接口工具,可能不少人會說爲何不用以前的,我以爲之後仍是會用的,最好能作到插件自動化生成api,可是對java開發註釋要求比較嚴格,隨意慢慢來吧,畢竟後面咱們還有不少路要走。