隨着先後端分離愈來愈廣泛, 後端接口規範也就愈來愈重要了. 一套良好的接口規範能夠提高工做效率, 減小溝通障礙.html
一般咱們都會採用 REST 方式來提供接口, 使用 JSON 來傳輸數據.前端
名詞 | 含義 |
---|---|
前端 | Web前端, APP端, 桌面端等一切屬於用戶界面的這一層 |
後端 | 即服務器端, 指一切屬於用戶界面之下的這一層 |
先後端接口 | 前端與後端進行數據交互的統稱, 也叫作數據接口, 屬於一種遠程調用, 通常指前端經過HTTP(ajax)請求獲取到的數據或者執行的某項操做. 爲確保先後端(工程師)的協做溝通, 通常由前端和後端一塊兒來定義接口的規範, 規範的內容通常包含接口的地址, 接口的輸入參數和輸出的數據格式(結構), 最終由後端來實現這些規範, 爲前端提供符合規範的接口 |
[前端] -------- ^ | | 先後端接口 | | -------- [後端]
在開發以前必定要先定義好接口規範, 至於接口應該由前端來定仍是後端來定, 這個還得看公司的具體狀況, 但必定要讓先後端都確認無誤, 特別是接口協商要點.java
以避免出現先後端分離以後最容易出現的扯皮現象. 特別是當你碰到作事不主動(無責任感)的後端, 什麼都要前端來催. 好比什麼接口又缺了一個字段沒有提供啦, 什麼又少了一個接口啦, 等等諸如此類. 後端不去熟悉業務, 也不看界面原型和需求, 只管把接口作完, 任務完成就萬事大吉了, 天天除了等前端通知哪裏要修改, 本身就像沒事人同樣.node
因此說定好接口, 先後端一塊兒來確認好接口是多麼的重要, 否則你就等着乾着急吧. 固然了, 想一次性完美地將全部接口都定義出來, 有點不太現實, 須要調整的狀況在所不免, 因此仍是但願後端可以主動一點, 先後端溝通的時候就輕鬆得多, 你們的效率就都提升了.android
由前端(APP端)和後端一塊兒協定接口規範的內容, 肯定每個接口的地址(URL), 輸入(request)和輸出(response), 必要的時候詳細註釋每個字段的含義和數據類型.git
具體須要定義哪些接口, 能夠按照下面的思路來整理github
null
的對應數據類型初始值, 例如對象類型的返回空對象({}
), 數組類型的返回空數組([]
), 其餘原始數據類型(string
/number
/boolean
...)也使用對應的默認值result.fieldName
result
爲 null
, 可想而知會報錯 Uncaught TypeError: Cannot read property 'fieldName' of null
"status": 1
http://a.res.com/path/to/img.png
這就是完整的, 前端直接使用這個 URL/path/to/img.png
這就是部分的, 通常省略域名部分, 前端須要本身拼接後才能使用 'http://a.res.com' + '/path/to/img.png'
1458885313711
, 或者參考 Date.prototype.toJSON 提供 ISO 標準格式(例如須要考慮時區時)2017年1月1日
JavaScript
會發生溢出, 形成獲得的數值錯誤
{"id": 362909601374617692}
前端拿到的值倒是: 362909601374617660
全部的接口定義在項目前端靜態文件目錄的 _mockserver.json
文件中, 啓動 puer-mock
服務, 便可使用這些接口得到符合規範的假數據, 也能夠查看接口文檔.web
具體 puer-mock
的詳細使用手冊和 _mockserver.json
如何配置接口請參考 puer-mock 項目, 或者參考項目中已經配置好的其餘接口.ajax
因爲接口規範的定義和接口的實際實現是分開的兩個部分, 並且涉及到多人協做, 所以在開發過程當中可能出現接口規範與實現不一樣步, 最終形成實際的接口不符合規範的定義, 接口規範就會慢慢失去存在的意義.json
爲了儘可能避免這種問題, 後端在實現接口的過程當中應該確保與接口規範保持一致, 一旦出現分歧, 必須同步修改接口規範, 儘量保持溝通.
接口根路徑 - Root Endpoint 推薦爲: http://api.yourdomain.com
或者 http://yourdomain.com/api
接口地址即接口的 URL, 定義時使用相對路徑(即不用帶上域名信息), 建議分模塊來定義, 推薦 REST 風格, 例如
GET /user/:id
表示獲取用戶信息POST /user
表示新增用戶向接口傳遞參數時, 若是是少許參數能夠做爲 URL query string 追加到接口的 URL 中, 或者做爲 Content-Type: application/x-www-form-urlencoded
放在請求體(body
)中(即表單提交的方式)
對於複雜的接口參數(例如嵌套了多層的數據結構), 推薦在 HTTP 請求體(body
)中包含一個 JSON 字符串做爲接口的參數, 並設置 Content-Type: application/json; charset=utf-8
.
例如
查詢 VIP 用戶的接口
POST /users?limit=10 HTTP/1.1 Content-Type: application/json; charset=utf-8 { "name": "hanmeimei", "isVip": true }
返回的響應體類型推薦爲 Content-Type: application/json; charset=utf-8
, 返回的數據包含在 HTTP 響應體中, 是一個 JSON Object. 該 Object 可能包含 3 個字段 data
, status
, statusInfo
HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 { "data": {}, "status": 0, "statusInfo": { "message": "給用戶的提示信息", "detail": "用於排查錯誤的詳細錯誤信息" } }
字段名 | 字段說明 |
---|---|
data | 業務數據 必須是任意 JSON 數據類型(number/string/boolean/object/array). 推薦始終返回一個 object (即再包一層)以便於擴展字段. 例如: 用戶數據應該返回 {"user":{"name":"test"}} , 而不是直接爲 {"name":"test"} |
status | 狀態碼 必須是 >= 0 的 JSON Number 整數.
|
statusInfo | 狀態信息 必須是任意 JSON 數據類型. 推薦始終返回一個 object 包含 message 和 detail 字段
|
例如
接口處理成功時接口返回的數據
{ "data": "api result" "status": 0 }
接口處理失敗時接口返回的數據
{ "status": 1, "statusInfo": { "message": "服務器正忙", "detail": { "exception": "java.util.List" } } }
這樣咱們就能夠很是容易地經過判斷 status 來處理數據了
if (!response.status) { // status 爲 0 或者沒有 status 字段時表示接口成功返回了數據 console.log(response.data); } else { // 失敗 console.error(response.status, response.statusInfo); // 統一由服務端返回給用戶的提示信息 alert(response.statusInfo.message); }
status
字段該如何取值採用先後端分離開發模式的項目愈來愈多, 前端負責調用後端的接口來展示界面, 若是有界面顯示異常, 須要有快速方便的手段來排查線上錯誤和定位出職責範圍
綜合了經驗總結和行業實踐, 最簡單有效的手段是制定出一套統一的錯誤碼規範, 協助多方人員來排查出接口的錯誤
例如
所以咱們肯定提示信息規範爲: 當後端接口調用出錯時, 接口提供一個用戶能夠理解的錯誤提示, 前端展現給用戶錯誤提示和錯誤碼, 給予用戶反饋
對於錯誤碼的規範, 參考行業實踐, 大體有兩種方案
A101
, B131
具體實踐以下
錯誤碼固定長度, 以區間來劃分錯誤類型(例如 HTTP 的狀態碼)
例如: 10404 表示 HTTP 請求 404 錯誤, 20000 表示 API 調用失敗, 30000 表明業務錯誤, 31000 表示業務A錯誤, 32000 表示業務B錯誤
錯誤碼可不固定長度, 以首字母來劃分錯誤類型, 可擴展性更好, 但實際運做仍是須要劃分區間
例如: H404 表示 HTTP 請求 404 錯誤, A100 表示 API 調用失敗, B100 表示業務A錯誤, B200 表示業務B錯誤
關於錯誤分類的原則, 咱們能夠根據發送請求的最終狀態來劃分
錯誤碼可不固定長度, 總體格式爲: 字母+數字
, 字母
做爲錯誤類型, 可擴展性更好, 數字
建議劃分區間來細分錯誤
例如:
A
for API: API 調用失敗(請求發送失敗)的錯誤, 例如 A100
表示 URL 非法H
for HTTP, HTTP 異常狀態的錯誤, 例如 H404
表示 HTTP 請求404錯誤B
for backend or business, 接口調用失敗的錯誤, 例如 B100
業務A錯誤, B200
業務B錯誤C
for Client: 客戶端錯誤, 例如 C100
表示解析 JSON 失敗發送 HTTP 請求 ┌───────────┴───────────┐ 發送成功¹ 發送失敗² │ │ ┌──────────┴──────────┐ A 例如: A100 得到 HTTP 響應 沒法得到 HTTP 響應³ │ │ HTTP status A 例如: A200 ┌──────────┴──────────┐ HTTP 成功(200-300) HTTP 異常 │ | {data, status, statusInfo} H${HTTP status} 例如: H404 ┌───────────┴───────────┐ 接口調用成功(status:0) 接口調用失敗 ┌────────┴────────┐ | 客戶端處理出錯 客戶端處理正常 B${status}${statusInfo.message} 例如: B100 | C 例如: C100 - 發送成功¹: 服務端收到了 HTTP 請求並返回了 HTTP 響應 - 發送失敗²: HTTP 請求沒有發送出去(例如因爲跨域被瀏覽器攔截不容許發送), 未到達服務端(即服務端沒有收到這個 HTTP 請求) - 沒法得到 HTTP 響應³: 服務端收到了請求並返回了響應, 但客戶端因爲某些緣由沒法得到 HTTP 響應, 例如請求的超時處理機制
${錯誤碼}
) ${HTTP 方法}
${HTTP URL}
${請求參數}
${請求選項}
${請求返回結果}
接口調用出錯(H404) GET https://domain.com {foo: bar} {option1: 'test'} {status: 404}
規範實現: weapp-backend-api
GET /contact
獲取聯繫人, POST /contact
新增/修改聯繫人362909601374617692
, 做爲 JSON 數據返回給前端, 前端拿到的值變成了 362909601374617660
{"sex": 1, "sexText": "男"}
{"pic": "https://domain.com/a.png"}
{"createTime": 1543195480357, "createTimeText": "2018年11月26日"}
有範雲協做 讓項目的協做姿式更有範兒
- 交互階段說明
- 交互設計師根據產品方的需求對產品進行行爲設計和界面設計的階段,主要產出物爲交互設計稿
- 開發工程師須要作的事情是針對產品需求、交互設計稿中的內容進行技術評審,爲產品方、交互設計師提供可行技術實現解決方案,對於多種不一樣解決方案需針對各類解決方案作分析說明,務必準確傳達各類方案的優缺點,並根據需求給出建議方案
- 系統設計說明
- 各端開發工程師針對產品需求說明、交互設計稿開始設計系統架構、拆分子系統、劃分子系統模塊、協調端與端之間的接口規範,這個階段各端根據實際狀況輸出若干系統設計說明書等文檔
- 除此以外更重要的是輸出端與端之間通訊的接口規範,而這個規範則能夠藉助 NEI 平臺 來完成
- 編碼階段說明
- 開發工程師根據系統設計階段的輸出,用代碼來實現這樣的系統,包括技術方案的選型、項目框架的搭建、工具及環境的配置等
- 其中有些工做能夠藉助於有範雲協做提供的自動化工具 NEI-Toolkit 來完成,好比項目的初始結構代碼、在 NEI平臺 上定義好的接口規範等
- 自測階段說明
- 各個端的工程師驗證本身編寫的代碼的正確性,按角色不一樣,測試方式也有全部不一樣
- 對於前端和移動端工程師來講,主要是須要測試各類可能的值會不會影響界面展現
- 對於服務端工程師來講,主要是測試提供給客戶端工程師使用的接口的正確性,對於不一樣的輸入參數是否返回了預期的結果
- 聯調階段說明
- 主要是連測試環境進行測試
- 對於前端和移動端工程師來講,主要是須要將本地容器提供的接口換成測試環境的接口
- 測試階段說明
- 開發工程師開發完成後提測的過程,是產品上線前的最後環節
- 測試工程師會對接 NEI 平臺生成接口測試用例代碼並集成到自動化測試平臺運行,若是NEI平臺的接口定義與實際提測的項目不符則這次提測失敗,需由開發對照 NEI 平臺檢查接口實現狀況,因此能夠保證 NEI 平臺上的接口定義始終與線上保持一致
參數名 說明 imei 國際移動設備身份碼 imsi 客戶端用戶標識 t TIMESTAMP,請求的時間戳 appkey 由服務端頒發的appkey sign md5簽名串。爲了減輕非法惡意請求,每次來自APP的請求都須要對請求參數進行簽名以實現安全認證 lng 手機上獲取的經度 lat 手機上獲取的緯度 ci 渠道標識,格式爲:channelId@應用名平臺客戶端版本,例如:1001@nzaom_android_1.0,其中1001表示應用寶
JSend | JSON API | JSON Schema | JSON-RPC | JWT | OAuth
Type Description Required Keys Optional Keys success All went well, and (usually) some data was returned. status, data fail There was a problem with the data submitted, or some pre-condition of the API call wasn't satisfied status, data error An error occurred in processing the request, i.e. an exception was thrown status, message code, data
最佳實踐:更好的設計你的 REST API | RESTful API 設計指南 | Best Practices for Designing a Pragmatic RESTful API | HTTP API Design Guide | The RESTful Cookbook | RESTful API 編寫指南
Restlet Studio - Web IDE for API design | Swagger | ReDoc | RAML | API Blueprint