【SpringBoot 2學習筆記】《二》封裝統一的接口返回格式

在各種中臺、微服務、分佈式等互聯網概念盛行的今天,部門承接的項目也逐漸開始採用的微服務框架,前後端分離方式。現在的軟件開發,隨着前後端任務的細分,相應的工作職責也就越來越清晰。現在項目開發的前端的技術棧和相應的生態圈都已經相當成熟,前端開發人員隨之走俏,地位也越來越高。

新開發系統中融合各種微應用的方式來構建生態系統,所以使用SpringBoot2對原有的產品按照微服務的模式進行拆分重構,本文主要介紹在重構過程中微服務Restful API風格,返回接口設計統一返回形式。

系統的整體架構示意圖如下:

 

※此圖是概要示意圖,省略了網關、消息中間件等,重點用來輔助理解API設計。

 

接口交互

根據目前發展趨勢來看,隨着前端設備種類的增多,前端和後端進行交互就越來越靈活多樣。因此,最好有一種統一的方式來進行前端設備與後端進行通信。RESTful架構是對MVC架構改進後所形成的一種架構,通過使用事先定義好的接口與不同的服務聯繫起來。在RESTful架構中,客戶端使用POST,DELETE,PUT和GET四種請求方式分別對指定的URI資源進行增刪改查操作。這種對資源的管理訪問方式具有強擴展性、結構清晰等特點,是目前比較成熟的一套互聯網應用程序的API設計架構。本文重點介紹後端服務器接收請求後,如何實現封裝業務數據返回前端。

返回格式

現在開發項目中,前端和後端並不是固定的搭配來同時進行同一個項目,在頻繁交替過程中,不能保證大家保持接口和調用形式的默契行,如果前端和後端,在沒有統一返回數據格式,就會給接口調試帶來較大的麻煩。不同的人員基於自身對RestFul的瞭解,按照自己的喜好來封裝接口返回的數據格式:

  • 張三:習慣返回一個編碼(code=0)並返回數據;

  • 李四:喜歡直接返回一個布爾類型變量(success=true),然後返回數據;

  • 王五:習慣在調用失敗時,返回一個狀態(status=0)並返回數據。

如上三個人的做法基本都沒有大問題,並沒有絕對的誰對誰錯,只要給前端人員正確的接口文檔,前端都可以調用接口。但是,如果沒有同意規則,在同一個項目中任由他們自由生長,隨着功能越來越多,就會帶來很大的麻煩。返回規則不一致,導致同一個前端,需要分別針對不同的接口做各種規則的適配。溝通後臺,每個人都有很多開發完成的接口,修改量巨大,牽一髮而動全身。所以,在項目開發初期,搭建基礎框架時,就要定好標準的接口數據返回格式,定義好全局的狀態碼。在同一個項目,必須遵循同一套接口返回格式,以便降低開發溝通成本。

後端返回給前端返回一般用JSON體方式,定義如下:

/**
 *  定義返回的基本數據格式
 * 
 *  {status=0, code=1001, msg='查詢成功', data=數據}
 *  {status=0, code=1002, msg='查詢成功無記錄', data=[]}
 *  {status=0, code=1003, msg='自定義業務msg', data=這是自定義的數據}
 *  {status=1, code=5001, msg='參數爲空或格式錯誤', data=[]}
 *  {status=1, code=5002, msg='查詢失敗', data=[]}
 */
public class BaseResult<T> {
​
  // 處理結果: 0 : 成功  1 : 失敗 。和錯誤編碼區分
  // 參數格式錯誤 賦值爲1 發生異常,查詢出錯 賦值爲1  查詢成功 沒有錯誤 都設定爲0 
  private Integer status;
  
  // 服務器返回的業務編碼
  private Integer code;
  
  // 服務器返回的提示信息(包括成功提示消息和錯誤消息)
  private String msg;
  
  // 服務器的返回數據(即使出錯,也要返回空對象,不能直接返回null)
  private T data;
​
}

※code返回業務編碼,開發同學們根據實際的業務功能自行封裝,隨着項目的進行逐步添加。例如:接口要返回用戶密碼異常,初始業務編碼可以設定爲1001。接下來有一個參數檢查異常,就加一個1002的狀態碼。這樣前端人員在得到返回值後,根據業務編碼就可以概要知道錯誤是什麼,再根據msg描述能夠快速定位問題,提高開發效率。

當然爲了規範化,我們可以參考HTTP請求返回的狀態碼來定義我們的業務消息:

#1000~1099 表示參數錯誤類信息
#1100~1199 表示XX業務類錯誤
#1200~1299 表示YY業務類異常
……
#9000~9099 表示DB訪問類信息

控制層Controller

通常會在controller層處理業務請求,並將請求結果返回給前端。下面是一個檢索微信公衆號列表信息的返回結果。

@RestController
@RequestMapping("/api/wechat")
public class WechatController {
  
  @Autowired
  WechatDataService wechatDataService;
​
  @GetMapping("/docs")
  public BaseResult<List<WechatDoc>> getWechatDocs() throws NewsException {
    return BaseResponse.makeOKRsp(wechatDataService.searchDocs(docType));
  }
}

返回結果

{
    "status": 0,
    "code": 1001,
    "msg": "信息查詢成功",
    "data": [
        {
            "hotsportName": "北京師範大學珠海分校教師XXX",
            "urlTime": "2019-11-05 00:54:38",
            "siteName": "微信",
            "evaluate": "正面"
        },
        {
            "hotsportName": "477名騎士用車輪丈量美麗金灣!多圖回顧“速度與激情”",
            "urlTime": "2019-11-03 20:27:43",
            "siteName": "微信",
            "evaluate": "正面"
        },       
        {
            "hotsportName": "科技賦能粵港澳大灣區文創產業發展",
            "urlTime": "2019-11-07 09:45:22",
            "siteName": "微信",
            "evaluate": "正面"
        }
    ]
}

 

後續優化

Controller中使用封裝的Result類,通過靜態方法的調用使得代碼比較簡化。後續我們可以繼續考慮代碼的優化,在控制層直接返回業務對象,通過攔截器的方式進行統一的返回值的封裝處理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章