封裝ResultVO實現統一返回結果
背景
為了在開發中,返回到前端的資料內容格式趨於一致,我們在開發過程中最好能夠將返回資料物件的格式進行約定,以便於開發對接過程中的約定速成;本章將帶你瞭解如何設計統一返回物件,以及與其相關的知識內容。
封裝返回結果物件
ResultVO物件封裝
通過RestFul介面開發的介面,一般含有介面執行狀態(成功、失敗、失敗描述、成功的資料返回物件)
因此我們可以將返回結果物件結構定義如下如下:
@Data @AllArgsConstructor @NoArgsConstructor @ApiModel(value = "統一請求的返回物件") public class ResultVO<T> { @ApiModelProperty(value = "錯誤程式碼") private Integer code; @ApiModelProperty(value = "訊息") private String msg; @ApiModelProperty(value = "對應返回資料") private T data; }
定義了統一的的返回物件,那麼一般我們需要考慮不同場景的輸出和呼叫;比如成功,失敗,或其他異常等情況的便捷呼叫。如果是因為某種業務原因需要返回失敗操作,一般包含有錯誤碼和錯誤資訊,更有勝者包含對應的錯誤堆疊異常明細;那麼就需要我們對於錯誤碼做比較好的規劃和設計了;
錯誤程式碼結構設計
這裡我們設計瞭如下的錯誤碼規劃,首先定義一個IErrorCode(錯誤程式碼的介面類),裡面定義兩個方法,即獲取錯誤碼和錯誤訊息的介面方法,如下
public interface IErrorCode { /** * 描述:得到錯誤碼 * @date 2020/11/21 **/ Integer getCode(); /** * 描述:得到錯誤訊息 * @Author Hank **/ String getMsg(); }
定義了介面類,然後我們再定義ErrorCode的介面實現列舉;如下
public enum ErrorCode implements IErrorCode { /*** * 1. 以下錯誤碼的定義,需要提前與前端溝通 * 2. 錯誤碼按模組進行錯誤碼規劃 * 3. 所有錯誤碼列舉類均需要實現錯誤碼介面類 */ SUCCESS(0,"操作成功"), SYSTEM_BUSY(10000,"系統繁忙,請稍後再試!"), FORM_VALIDATION_ERROR(10001,"表單驗證錯誤"), // 使用者登入方面錯誤碼 LOGIN_ERROR(101001, "你還未登陸,請及時登陸"), TOKEN_ERROR(101002, "登入憑證已過期,請重新登入"); private Integer code; private String msg; ErrorCode(Integer code,String message){ this.code=code; this.msg=message; } @Override public Integer getCode() { return code; } @Override public String getMsg() { return msg; } }
小試牛刀
做了如上定義,我們就可以在對應的方法中去進行使用了,使用過程中,我們可以直接 return ResultVO;如下:
@RestController @RequestMapping(value = "/test") @Api(tags = "基礎模組介面") public class IndexCtrl { @ApiOperation(value = "hello 介面",notes = "hello介面的描述") @GetMapping(value = "/index") public ResultVO hello(){ ResultVO rv=new ResultVO(); rv.setCode(ErrorCode.SUCCESS.getCode()); rv.setMsg(ErrorCode.SUCCESS.getMsg()); return rv; } }
效果增強
從上面的程式碼中我們可以看到,要做這樣的返回,貌似還是比較繁瑣,基本上要四行程式碼才能有一個完成的返回,並且ErrorCode類是固定的。
我們嘗試將上面程式碼再做一次修改,希望達到如下效果:
- 在使用返回物件的時候能夠儘量簡單,或開發中無感
- 各個模組可以定義自己的錯誤碼實現類,融入到基礎框架中
ResultVO物件增強
需要達到如上兩點,我們首先修改ResultVO類,豐富建構函式和支援列舉方法的傳值,程式碼如下:
@Data @AllArgsConstructor @NoArgsConstructor @ApiModel(value = "統一請求的返回物件") public class ResultVO<T> { @ApiModelProperty(value = "錯誤程式碼") private Integer code; @ApiModelProperty(value = "訊息") private String msg; @ApiModelProperty(value = "對應返回資料") private T data; public ResultVO(int code, String mesage) { setCode(code); setMsg(mesage); } public ResultVO(IErrorCode errorCode, T data) { setCodeMessage(errorCode); setData(data); } public ResultVO setCodeMessage(IErrorCode codeMessage) { setCode(codeMessage.getCode()); setMsg(codeMessage.getMsg()); return this; } }
封裝助手工具
完成如上,我們還可以封裝一個工具類RV,方便使用:
public class RV { /*** * 成功的返回物件 * @param data * @return */ public static ResultVO success(Object data) { return new ResultVO(ErrorCode.SUCCESS,data); } /** * 失敗的返回物件 * @Param: ErrCodeInterface * @return: [ResultVO] * **/ public static ResultVO fail(IErrorCode errorCode) { return new ResultVO().setCodeMessage(errorCode); } /** * 描述: 通過errorCode和資料物件引數,構建一個新的物件 * @param [errorCode, data] * @return: [ResultVO] **/ public static ResultVO result(IErrorCode errorCode,Object data){ return new ResultVO(errorCode,data); } }
簡潔性驗證
還是以上面應用程式碼為例,最終程式碼修改如下
@RestController @RequestMapping(value = "/test") @Api(tags = "基礎模組介面") public class IndexCtrl { @ApiOperation(value = "hello 介面",notes = "hello介面的描述") @GetMapping(value = "/index") public ResultVO hello(){ return RV.success(null);; } }
擴充套件性驗證
前面我們描述了那麼多,這裡所謂的擴充套件性怎麼理解呢,這裡所謂的擴充套件性,更多是在不同業務系統,對於錯誤碼的定義的擴充套件,比如一個我們專案裡面,分成了多個不同的模組,但每個模組的實現都依賴於基礎common包中封裝的工具;對於錯誤碼,我們不可能一次性在common中定義出所有模組的錯誤碼;因此我們在設計的時候,特意定義了IErrorCode介面庫類,預設由ErrorCode做了實現;
也就意味著,在common包中定義的這些類,沒有特殊情況不用高頻的修改,那我們在其他業務模組要定義自己的錯誤碼可以怎麼做呢。
如下,我們只需要在對應的業務模組,定義自己的錯誤碼列舉類即可,比如在裝置管理模組
/** * new-retail * <p> * 錯誤碼定義範圍 10101-10200 * </p> * @author Hank * @since 2020-11-21 */ public enum DeviceErrorCode implements IErrorCode { DEVICE_OFFLINE(10101,"裝置已離線"), COMMAND_ERROR(10102,"指令錯誤"); private Integer code; private String msg; DeviceErrorCode(Integer code,String message){ this.code=code; this.msg=message; } @Override public Integer getCode() { return code; } @Override public String getMsg() { return msg; } }
在Controller中的應用
我們根據裝置管理模組定義了對應的錯誤列舉類,也就意味著,在做該模組實際業務的時候,我們可以直接對外丟擲對應的錯誤碼,而不必考慮與其他模組的適配問題;其應用如下;
@PostMapping(value = "/restart") public ResultVO restart(@RequestBody DeviceInfo deviceInfo) { load(deviceInfo); if (!deviceInfo.online()) { return RV.result(DeviceErrorCode.DEVICE_OFFLINE, deviceInfo); } return RV.success(deviceInfo); }
在異常中的應用
在前章節我們講到異常BusinessException的封裝,但是我們只是做了簡單的繼承RuntimeException而已,沒有繼續深入;那我們再結合本章所講到的錯誤程式碼進行完善增強
/** * new-retail-lesson * <p> * 自定義業務異常類 * </p> * @author Hank * @since 2020-10-31 */ public class BusinessException extends RuntimeException { private int code; private String detailMessage; public BusinessException(int code, String message) { super(message); this.code = code; this.detailMessage = message; } public BusinessException(IErrorCode errorCode) { this(errorCode.getCode(),errorCode.getMsg()); } public int getCode() { return code; } public String getDetailMessage() { return detailMessage; } }
從上面程式碼中,我們可以看出,我們在BusinessException中增加了兩個變數code,detailMessage;並對建構函式做了多樣性處理,值得注意的是我們在建構函式中,增加了IErrorCode介面的引數;
既然在異常做了增強,那我們的異常攔截處也需要做響應的處理,找到我們前面定義的全域性異常類GlobalExceptionHander,在對應的攔截BusinessException處做對應的處理,如下
@RestControllerAdvice public class GlobalException { /** * 描述:業務異常攔截 * @param * @date 2020/10/31 * @Author Hank **/ @ExceptionHandler(value = BusinessException.class) public ResultVO businessException(BusinessException e){ ResultVO rv= new ResultVO(e.getCode(),e.getDetailMessage()); return rv; } }
完成了上面的基礎工作,我們接下來看下在編碼中能夠如何使用;
- 在Controller中有業務異常丟擲時,拿我們剛才的例子,程式碼調整如下,不用直接return,可以直接丟擲對應的業務異常,由GlobalExceptionHander來兜底就行
@PostMapping(value = "/restart") public ResultVO restart(@RequestBody DeviceInfo deviceInfo) { load(deviceInfo); if (!deviceInfo.online()) { throw new BusinessException(DeviceErrorCode.DEVICE_OFFLINE); } return RV.success(deviceInfo); }
- 在業務程式碼中,可以直接丟擲對應的業務異常,最終由GlobalException來兜底
當然在異常處理部分,我們可以根據場景需要,定義不同型別的異常,結構與上面類似,即可達到相同的效果
小結
上面我們主要介紹了
- ResultVO物件的封裝
- 然後介紹了統一錯誤程式碼介面類和錯誤列舉類的設計
- 以及結合ResultVO物件和IErrorCode介面做了整合
- 通過IErrorCode與自定義異常結合再結合全域性異常攔截與ResultVO物件結合做全域性異常攔截;
- 最後還介紹了結合定義的ResultVO物件和IErrorCode介面類,可以如何做到異常方面的擴充套件。
以上為本章介紹的所有內容,希望對你有幫助,如果你在統一返回物件封裝和異常封裝方面有更好的不同實踐,也歡迎在留言區進行留言。
想要了解更多資訊,可關注本公眾號(一起學開源);或請長按以下二維碼新增助手。將拉你加入社群進行更多交流
相關文章
- 統一結果封裝封裝
- springboot返回結果包裝統一返回格式Spring Boot
- ASP.NET Core WebApi返回結果統一包裝實踐ASP.NETWebAPI
- 方法返回資料統一封裝封裝
- 全域性統一返回結果類
- Solon 統一的返回結果調整
- [hyperf]關於資料返回封裝的另一種實現思考封裝
- 統一返回結果狀態資訊類
- 8 Spring Boot返回資料及異常統一封裝Spring Boot封裝
- MyBatis 返回結果MyBatis
- iOS FMDB有返回結果集和無返回結果集iOS
- 封裝springmvc處理ajax請求結果封裝SpringMVC
- Django實現統一包裝介面返回值資料格式Django
- springboot2.0-統一處理返回結果和異常情況Spring Boot
- FastAPI 學習之路(五十九)封裝統一的json返回處理工具ASTAPI封裝JSON
- 通用結果類用於返回響應結果
- Python返回多個結果Python
- vue實現的封裝全域性filter並統一管理操作示例Vue封裝Filter
- 【JavaScript框架封裝】實現一個類似於JQuery的動畫框架的封裝JavaScript框架封裝jQuery動畫
- JavaScript中Typeof返回的結果JavaScript
- 【JavaScript框架封裝】實現一個類似於JQuery的CSS樣式框架的封裝JavaScript框架封裝jQueryCSS
- 判斷 ORM 返回結果為空ORM
- SpringCloud FeignClient呼叫返回結果為null。SpringGCCloudclientNull
- ApiResponse介面統一響應封裝API封裝
- aardio 實現封裝繼承多型封裝繼承多型
- AOP的具體實踐-簡化結果返回的處理
- canvas簡單封裝一個echarts實現不了的餅圖Canvas封裝Echarts
- fiddler 修改請求介面的返回結果
- item_get_app資料返回結果APP
- MySQL 按指定 ID 順序返回結果MySql
- Mysql按指定 ID 順序返回結果MySql
- 如何設計API介面,實現統一格式返回?API
- 如何設計 API 介面,實現統一格式返回?API
- mysql返回一個結果集的儲存過程小例子MySql儲存過程
- java使用mybatis 呼叫函式返回一個遊標結果集JavaMyBatis函式
- API介面開發(一):介面開發返回結果解決方案API
- Api 介面的統一響應封裝API封裝
- flutter dio網路請求封裝實現Flutter封裝