設(shè)計 API 接口,實現(xiàn)統(tǒng)一格式返回

來源:老顧聊技術(shù)

前言

在移動互聯(lián)網(wǎng),分布式、微服務(wù)盛行的今天,現(xiàn)在項目絕大部分都采用的微服務(wù)框架,前后端分離方式。
一般系統(tǒng)的大致整體架構(gòu)圖如下:


file

接口交互

前端和后端進行交互,前端按照約定請求URL路徑,并傳入相關(guān)參數(shù),后端服務(wù)器接收請求,進行業(yè)務(wù)處理,返回數(shù)據(jù)給前端。
針對URL路徑的restful風格,以及傳入?yún)?shù)的公共請求頭的要求(如:app_version,api_version,device等),這里就不介紹了,注重介紹一下后端服務(wù)器如何實現(xiàn)把數(shù)據(jù)返回給前端

返回格式
后端返回給前端我們一般用JSON體方式,定義如下:

{
 #返回狀態(tài)碼
 code:integer, 
 #返回信息描述
 message:string,
 #返回值
 data:object
}

CODE狀態(tài)碼

code返回狀態(tài)碼,一般小伙伴們是在開發(fā)的時候需要什么,就添加什么。
如接口要返回用戶權(quán)限異常,我們加一個狀態(tài)碼為101吧,下一次又要加一個數(shù)據(jù)參數(shù)異常,就加一個102的狀態(tài)碼。這樣雖然能夠照常滿足業(yè)務(wù),但狀態(tài)碼太凌亂了
我們應(yīng)該可以參考HTTP請求返回的狀態(tài)碼
:下面是常見的HTTP狀態(tài)碼:
200 – 請求成功
301 – 資源(網(wǎng)頁等)被永久轉(zhuǎn)移到其它URL
404 – 請求的資源(網(wǎng)頁等)不存在
500 – 內(nèi)部服務(wù)器錯誤


file

我們可以參考這樣的設(shè)計,這樣的好處就把錯誤類型歸類到某個區(qū)間內(nèi),如果區(qū)間不夠,可以設(shè)計成4位數(shù)。

1000~1999 區(qū)間表示參數(shù)錯誤

2000~2999 區(qū)間表示用戶錯誤

3000~3999 區(qū)間表示接口異常

這樣前端開發(fā)人員在得到返回值后,根據(jù)狀態(tài)碼就可以知道,大概什么錯誤,再根據(jù)message相關(guān)的信息描述,可以快速定位。

Message

這個字段相對理解比較簡單,就是發(fā)生錯誤時,如何友好的進行提示。一般的設(shè)計是和code狀態(tài)碼一起設(shè)計,如


file

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


file

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

Data

返回數(shù)據(jù)體,JSON格式,根據(jù)不同的業(yè)務(wù)又不同的JSON體。
我們要設(shè)計一個返回體類Result


file

控制層Controller

我們會在controller層處理業(yè)務(wù)請求,并返回給前端,以order訂單為例


file

我們看到在獲得order對象之后,我們是用的Result構(gòu)造方法進行包裝賦值,然后進行返回。小伙伴們有沒有發(fā)現(xiàn),構(gòu)造方法這樣的包裝是不是很麻煩,我們可以優(yōu)化一下。

美觀優(yōu)化

我們可以在Result類中,加入靜態(tài)方法,一看就懂


file

那我們來改造一下Controller


file

代碼是不是比較簡潔了,也美觀了。

優(yōu)雅優(yōu)化

上面我們看到在Result類中增加了靜態(tài)方法,使得業(yè)務(wù)處理代碼簡潔了。但小伙伴們有沒有發(fā)現(xiàn)這樣有幾個問題:
1、每個方法的返回都是Result封裝對象,沒有業(yè)務(wù)含義
2、在業(yè)務(wù)代碼中,成功的時候我們調(diào)用Result.success,異常錯誤調(diào)用Result.failure。是不是很多余
3、上面的代碼,判斷id是否為null,其實我們可以使用hibernate validate做校驗,沒有必要在方法體中做判斷。
我們最好的方式直接返回真實業(yè)務(wù)對象,最好不要改變之前的業(yè)務(wù)方式,如下圖


file

這個和我們平時的代碼是一樣的,非常直觀,直接返回order對象,這樣是不是很完美。那實現(xiàn)方案是什么呢?

實現(xiàn)方案

小伙伴們怎么去實現(xiàn)是不是有點思路,在這個過程中,我們需要做幾個事情
1、定義一個注解@ResponseResult,表示這個接口返回的值需要包裝一下
2、攔截請求,判斷此請求是否需要被@ResponseResult注解
3、核心步驟就是實現(xiàn)接口ResponseBodyAdvice和@ControllerAdvice,判斷是否需要包裝返回值,如果需要,就把Controller接口的返回值進行重寫。
注解類
用來標記方法的返回值,是否需要包裝


file

攔截器

攔截請求,是否此請求返回的值需要包裝,其實就是運行的時候,解析@ResponseResult注解


file

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

重寫返回體

file

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


file

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

重寫Controller

file

在控制器類上或者方法體上加上@ResponseResult注解,這樣就ok了,簡單吧。到此返回的設(shè)計思路完成,是不是又簡潔,又優(yōu)雅。

總結(jié)

這個方案還有沒有別的優(yōu)化空間,當然是有的。如:每次請求都要反射一下,獲取請求的方法是否需要包裝,其實可以做個緩存,不需要每次都需要解析。當然整體思路了解,小伙伴們就可以在此基礎(chǔ)上面自行擴展。謝謝?。?!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原文地址:https://github.com/kuitos/kuitos.github.io/issues/9 ...
    沉默的魚fish閱讀 1,634評論 0 0
  • 1.abstract class 和interface 有什么區(qū)別? 抽象類可以有構(gòu)造方法 接口不行 抽象類可以有...
    sunnysans閱讀 966評論 0 1
  • 在人生的道路上,難免會遇到挫折。不管是你自己,還是你身邊的人。經(jīng)歷挫折有人會積極面對,吸取教訓(xùn),更快成長。有人會用...
    船長時間閱讀 211評論 1 0
  • 宙斯秀美雅客才 , 舒袖姿開醉情懷。 含苞怒放花羞澀, 疑是仙駕祥云來。 宛若仕女舞蹁躚, 野生草根上案臺。 初春...
    咪咪139318閱讀 573評論 6 27
  • 不用萬年歷,不用六十花甲表,只需記住兩點: 一、天干地支序號。天干序號:甲1、乙2、丙3、丁4、戊5、已6、庚7...
    羅茂新閱讀 20,455評論 0 1

友情鏈接更多精彩內(nèi)容