前後端完全分離之API設計
背景
API就是開發者使用的介面。我的目標不僅是能用,而且好用, 跨平臺(PC, Android, IOS, etc...)使用; 本文將詳細介紹API的設計及異常處理, 並將異常資訊進行封裝友好地反饋給前端.
上篇文章前後端完全分離初探只是講了些寬泛的概念, 接下來的文章將直接上乾貨, 乾貨的原始碼會掛在github
上.
前後端完全分離後, 前端和後端如何互動?
答: 通過雙方協商好的API.
接下來我分享我自己設計的API介面, 歡迎各位朋友指教.
API設計理念
- 將涉及的實體抽象成資源, 即按
id
訪問資源, 在url
上做文章, 以後再也不用為url
起名字而苦惱了. - 使用
HTTP
動詞對資源進行CRUD
(增刪改查); get->查, post->增, put->改, delete->刪. - URL命名規則, 對於資源無法使用一個單數名詞表示的情況, 我使用中橫線(
-
)連線.- 資源採用名詞命名, e.g: 產品 -> product
- 新增資源, e.g: 新增產品, url -> /product , verb -> POST
- 修改資源, e.g: 修改產品, url -> /products/{id} , verb -> PUT
- 資源詳情, e.g: 指定產品詳情, url -> /products/{id} , verb -> GET
- 刪除資源, e.g: 刪除產品, url -> /products/{id} , verb -> DELETE
- 資源列表, e.g: 產品列表, url -> /products , verb -> GET
- 資源關聯關係, e.g: 收藏產品, url -> /products/{id}/star , verb -> PUT
- 資源關聯關係, e.g: 刪除收藏產品, url -> /products/{id}/star , verb -> DELETE
目前我API的設計只涉及這兩點, 至於第三點HATEOAS
(Hypermedia As The Engine Of Application State)那就由讀者自己去選擇了.
專案地址
本文中只涉及了設計的理念, 具體的實現請下載原始碼rest-api, 專案內寫了比較詳細的註釋.
專案實戰
實戰將從業務場景出發, 詳細介紹如何使用HTTP verb對資源進行操作(狀態轉移
), 使用JSON返回結果(資源表述
), 並定義JSON的基礎結構.
JSON結構
requestParams:
{
}
responseBody:
{
"meta": {
},
"data": {
}
}
meta
中封裝操作成功或失敗的訊息, data
中封裝返回的具體資料.
當新建商品或更新產品時, 相關屬性封裝在JSON中, 通過POST或PUT傳送,
{
"name": "Apple Watch SPORT",
"description": "Sport 系列的錶殼材料為輕巧的銀色及深空灰色陽極氧化鋁金屬,強化 Ion-X 玻璃材質為螢幕提供保護。搭配高效能 Fluoroelastomer 錶帶,共有 5 款繽紛色彩。"
}
當使用者對商品進行操作後, 將得到響應結果,
GET, POST, PUT操作成功, 返回如下結果
{
"meta": {
"code": 201,
"message": "建立成功"
},
"data": {
"id": "5308e9c2-a4ce-4dca-9373-cc1ffe63d5f9",
"name": "Apple Watch SPORT",
"description": "Sport 系列的錶殼材料為輕巧的銀色及深空灰色陽極氧化鋁金屬,強化 Ion-X 玻璃材質為螢幕提供保護。搭配高效能 Fluoroelastomer 錶帶,共有 5 款繽紛色彩。"
}
}
DELETE操作成功, 返回如下結果
{
"meta": {
"code": 204,
"message": "刪除成功"
}
}
業務場景一
電商網站的管理員對商品進行新增,編輯,刪除,瀏覽的操作; 暫時不考慮認證授權, 只關注對商品的操作.
為了以後便於做分散式, 所有資源id(表主鍵)均採用uuid.
新增商品
1, url: /api/product
2, method: POST
3, requestParams:
{
"name": "Apple Watch SPORT",
"description": "Sport 系列的錶殼材料為輕巧的銀色及深空灰色陽極氧化鋁金屬,強化 Ion-X 玻璃材質為螢幕提供保護。搭配高效能 Fluoroelastomer 錶帶,共有 5 款繽紛色彩。"
}
4, responseBody
{
"meta": {
"code": 201,
"message": "建立成功"
},
"data": {
"id": "5308e9c2-a4ce-4dca-9373-cc1ffe63d5f9",
"name": "Apple Watch SPORT",
"description": "Sport 系列的錶殼材料為輕巧的銀色及深空灰色陽極氧化鋁金屬,強化 Ion-X 玻璃材質為螢幕提供保護。搭配高效能 Fluoroelastomer 錶帶,共有 5 款繽紛色彩。"
}
}
編輯商品
1, url: /api/products/{id}
2, method: PUT
3, requestParams:
{
"name": "iPhone 6",
"description": "此次蘋果釋出會釋出了iPhone 6與iPhone 6 Plus,搭載iOS 8,尺寸分別是4.7和5.5英寸。外觀設計不再稜角分明,表層玻璃邊有一個弧度向下延伸,與陽極氧化鋁金屬機身邊框銜接。機身背部採用三段式設計。機身更薄,續航能力更強。"
}
4, responseBody
{
"meta": {
"code": 200,
"message": "修改成功"
},
"data": {
"id": "5308e9c2-a4ce-4dca-9373-cc1ffe63d5f9",
"name": "iPhone 6",
"description": "此次蘋果釋出會釋出了iPhone 6與iPhone 6 Plus,搭載iOS 8,尺寸分別是4.7和5.5英寸。外觀設計不再稜角分明,表層玻璃邊有一個弧度向下延伸,與陽極氧化鋁金屬機身邊框銜接。機身背部採用三段式設計。機身更薄,續航能力更強。"
}
}
刪除商品
1, url: /api/products/{id}
2, method: DELETE
3, responseBody
{
"meta": {
"code": 204,
"message": "刪除成功"
},
"data": {}
}
獲取商品詳情
1, url: /api/products/{id}
2, method: GET
3, responseBody
刪除前
{
"meta": {
"code": 200,
"message": "查詢成功"
},
"data": {
"id": "5308e9c2-a4ce-4dca-9373-cc1ffe63d5f9",
"name": "Apple Watch SPORT",
"description": "Sport 系列的錶殼材料為輕巧的銀色及深空灰色陽極氧化鋁金屬,強化 Ion-X 玻璃材質為螢幕提供保護。搭配高效能 Fluoroelastomer 錶帶,共有 5 款繽紛色彩。"
}
}
刪除後
{
"meta": {
"code": 404,
"message": "指定產品不存在"
}
}
獲取商品列表(未分頁)
1, url: /api/products
2, method: GET
3, responseBody
{
"meta": {
"code": 200,
"message": "獲取全部商品成功"
},
"data": [
{
"id": "5308e9c2-a4ce-4dca-9373-cc1ffe63d5f9",
"name": "Apple Watch SPORT",
"description": "Sport 系列的錶殼材料為輕巧的銀色及深空灰色陽極氧化鋁金屬,強化 Ion-X 玻璃材質為螢幕提供保護。搭配高效能 Fluoroelastomer 錶帶,共有 5 款繽紛色彩。"
},
{
"id": "9db1992a-c342-4ff0-a2a4-aeb3dbfd93f6",
"name": "Apple Watch SPORT",
"description": "Sport 系列的錶殼材料為輕巧的銀色及深空灰色陽極氧化鋁金屬,強化 Ion-X 玻璃材質為螢幕提供保護。搭配高效能 Fluoroelastomer 錶帶,共有 5 款繽紛色彩。"
},
{
"id": "4481619b-45c5-4729-9539-f93bb01f10d8",
"name": "Apple Watch SPORT",
"description": "Sport 系列的錶殼材料為輕巧的銀色及深空灰色陽極氧化鋁金屬,強化 Ion-X 玻璃材質為螢幕提供保護。搭配高效能 Fluoroelastomer 錶帶,共有 5 款繽紛色彩。"
}
]
}
業務場景二
業務場景一
中只涉及了單個資源的操作, 但實際場景中還有些關聯操作; 如使用者去電商網站瀏覽商品, 並收藏了一些商品, 之後又取消收藏了部分商品.
暫時不考慮使用者認證授權, 以後加了token
後, 使用者資訊可以從中獲取.
收藏商品
1, url: /api/products/{id}/star
2, method: PUT
3, responseBody
{
"meta": {
"code": 200,
"message": "收藏商品[5308e9c2-a4ce-4dca-9373-cc1ffe63d5f9]成功"
},
"data": [
{
"id": "5308e9c2-a4ce-4dca-9373-cc1ffe63d5f9",
"name": "iPhone 6",
"description": "此次蘋果釋出會釋出了iPhone 6與iPhone 6 Plus,搭載iOS 8,尺寸分別是4.7和5.5英寸。外觀設計不再稜角分明,表層玻璃邊有一個弧度向下延伸,與陽極氧化鋁金屬機身邊框銜接。機身背部採用三段式設計。機身更薄,續航能力更強。"
}
]
}
取消收藏商品
1, url: /api/products/{id}/star
2, method: DELETE
3, responseBody
{
"meta": {
"code": 200,
"message": "刪除收藏商品[5308e9c2-a4ce-4dca-9373-cc1ffe63d5f9]成功"
},
"data": []
}
自定義異常和異常處理
所有自定義異常繼承RuntimeException, 在業務層丟擲, 統一在Controller層進行處理.
異常分為全域性異常和區域性異常, 例如http method unsupported(405), unauthorized(401), accessDenied(403), not found(404)等屬於全域性異常; 針對對獨立業務的一些異常屬於區域性異常, 例如產品編輯出錯;
異常在Controller中進行處理, 並封裝成json返回給前端, 封裝後的資料如下, 相關實現見原始碼;
{
"meta": {
"code": 404,
"message": "指定產品不存在"
}
}
{
"meta": {
"code": 405,
"message": "Request method 'POST' not supported"
}
}
專案執行截圖部分
本系列文章
- 前後端完全分離初探
- 前後端完全分離之API設計
- 前後端完全分離之安全認證與授權-上
- 前後端完全分離之安全認證與授權-下
- 前後端完全分離之前端模組化開發
- 前後端完全分離之前端路由系統
- 前後端完全分離之後端面向服務的模組化開發
原文出自 前後端完全分離之API設計, 歡迎轉載, 轉載請註明出處.
相關文章
- 前後端分離之更好的mock你的後端api後端MockAPI
- 前後端分離之Ajax入門後端
- 前後分離模型之封裝 Api 呼叫模型封裝API
- 前後端分離架構中的介面設計後端架構
- 再談前後端分離後端
- 前後端分離那些事後端
- 淺談前後端分離後端
- 前後端分離——使用OSS後端
- 前後端分離後的前端時代後端前端
- 前後端分離後模組開發後端
- ???前後端分離模式的思考???後端模式
- 前後端分離——資料mock後端Mock
- vue前後端分離修改webpackVue後端Web
- 前後端分離整合SpringSecurity後端SpringGse
- 前後端分離,最佳實踐後端
- 淺談WEB前後端分離Web後端
- 什麼是前後端分離?後端
- 前後端分離實踐有感後端
- 從MVC到前後端分離MVC後端
- 前後端分離Ajax入門後端
- laravel+vue前後端分離之伺服器端配置LaravelVue後端伺服器
- Web系統開發構架再思考-前後端的完全分離Web後端
- Django+Vue.js搭建前後端分離專案 web前後端分離專案實踐DjangoVue.js後端Web
- 基於SpringCloud+vue(ElementUI)+mySQL前後端分離設計之–搭建後臺管理系統SpringGCCloudVueUIMySql後端
- 以api文件為中心--前後端分開發離新思維API後端
- 您是否真的需要實現前後端分離的API? -DEV社群後端APIdev
- Flask前後端分離專案案例Flask後端
- 從部署上做到前後端分離後端
- 前後端分離的優缺點後端
- 實現前後端分離的心得後端
- 簡單的前後端分離 Cas後端
- Laravel 前後端分離 csrf 防護Laravel後端
- 實踐中的前後端分離後端
- Cloudera Manager 前後端分離部署方法Cloud後端
- 前後端分離之JWT(JSON Web Token)的使用後端JWTJSONWeb
- 前後端分離時代,Java 程式設計師的變與不變!後端Java程式設計師
- 分散式之閒侃前後端分離的必要性分散式後端
- 前後端分離,如何在前端專案中動態插入後端API基地址?(in docker)後端前端APIDocker