看看人家那后端API接口寫得,那叫一個優(yōu)雅!

需要說明的是,有些小伙伴會回復說,這個架構太簡單了吧,太low了,什么網關啊,緩存啊,消息中間件啊,都沒有。因為老顧這篇主要介紹的是API接口,所以我們聚焦點,其他的模塊小伙伴們自行去補充。
接口交互
前端和后端進行交互,前端按照約定請求URL路徑,并傳入相關參數(shù),后端服務器接收請求,進行業(yè)務處理,返回數(shù)據給前端。
針對URL路徑的restful風格,以及傳入參數(shù)的公共請求頭的要求(如:app_version,api_version,device等),老顧這里就不介紹了,小伙伴們可以自行去了解,也比較簡單。
著重介紹一下后端服務器如何實現(xiàn)把數(shù)據返回給前端?
返回格式
{
#返回狀態(tài)碼
code:integer,
#返回信息描述
message:string,
#返回值
data:object
}CODE狀態(tài)碼
:下面是常見的HTTP狀態(tài)碼:
200 - 請求成功
301 - 資源(網頁等)被永久轉移到其它URL
404 - 請求的資源(網頁等)不存在
500 - 內部服務器錯誤
我們可以參考這樣的設計,這樣的好處就把錯誤類型歸類到某個區(qū)間內,如果區(qū)間不夠,可以設計成4位數(shù)。
#1000~1999 區(qū)間表示參數(shù)錯誤
#2000~2999 區(qū)間表示用戶錯誤
#3000~3999 區(qū)間表示接口異常
這樣前端開發(fā)人員在得到返回值后,根據狀態(tài)碼就可以知道,大概什么錯誤,再根據message相關的信息描述,可以快速定位。

再在枚舉中定義,狀態(tài)碼

狀態(tài)碼和信息就會一一對應,比較好維護。
Data

控制層Controller

美觀優(yōu)化

那我們來改造一下Controller

代碼是不是比較簡潔了,也美觀了。
優(yōu)雅優(yōu)化
上面我們看到在Result類中增加了靜態(tài)方法,使得業(yè)務處理代碼簡潔了。但小伙伴們有沒有發(fā)現(xiàn)這樣有幾個問題:
1、每個方法的返回都是Result封裝對象,沒有業(yè)務含義
2、在業(yè)務代碼中,成功的時候我們調用Result.success,異常錯誤調用Result.failure。是不是很多余
3、上面的代碼,判斷id是否為null,其實我們可以使用hibernate validate做校驗,沒有必要在方法體中做判斷。

這個和我們平時的代碼是一樣的,非常直觀,直接返回order對象,這樣是不是很完美。那實現(xiàn)方案是什么呢?
實現(xiàn)方案
小伙伴們怎么去實現(xiàn)是不是有點思路,在這個過程中,我們需要做幾個事情
1、定義一個注解@ResponseResult,表示這個接口返回的值需要包裝一下
2、攔截請求,判斷此請求是否需要被@ResponseResult注解
3、核心步驟就是實現(xiàn)接口ResponseBodyAdvice和@ControllerAdvice,判斷是否需要包裝返回值,如果需要,就把Controller接口的返回值進行重寫。
注解類


此代碼核心思想,就是獲取此請求,是否需要返回值包裝,設置一個屬性標記。

上面代碼就是判斷是否需要返回值包裝,如果需要就直接包裝。這里我們只處理了正常成功的包裝,如果方法體報異常怎么辦?處理異常也比較簡單,只要判斷body是否為異常類。

怎么做全局的異常處理,篇幅原因,老顧這里就不做介紹了,只要思路理清楚了,自行改造就行。

在控制器類上或者方法體上加上@ResponseResult注解,這樣就ok了,簡單吧。到此返回的設計思路完成,是不是又簡潔,又優(yōu)雅。
總結
這個方案還有沒有別的優(yōu)化空間,當然是有的。如:每次請求都要反射一下,獲取請求的方法是否需要包裝,其實可以做個緩存,不需要每次都需要解析。當然整體思路了解,小伙伴們就可以在此基礎上面自行擴展。謝謝!!!
