這個例子將模仿拋出各種exception,幷包裝在CommonResult中進行統一的返回
我們先來給出項目中的錯誤碼的枚舉類,這裏挖坑,後面填
//枚舉項目中的錯誤碼
public enum ServiceExceptionEnum {
//錯誤碼設計的規則
/**
* 服務異常
*
* 參考 https://www.kancloud.cn/onebase/ob/484204 文章
*
* 一共 10 位,分成四段
*
* 第一段,1 位,類型
* 1 - 業務級別異常
* 2 - 系統級別異常
* 第二段,3 位,系統類型
* 001 - 用戶系統
* 002 - 商品系統
* 003 - 訂單系統
* 004 - 支付系統
* 005 - 優惠劵系統
* ... - ...
* 第三段,3 位,模塊
* 不限制規則。
* 一般建議,每個系統裏面,可能有多個模塊,可以再去做分段。以用戶系統爲例子:
* 001 - OAuth2 模塊
* 002 - User 模塊
* 003 - MobileCode 模塊
* 第四段,3 位,錯誤碼
* 不限制規則。
* 一般建議,每個模塊自增。
*/
//===========系統級別============
SUCCESS(0, "成功"),
SYS_ERROR(2001001000,"服務端發生異常"),
MISSING_REQUEST_PARAM_ERROR(2001001001,"參數缺失"),
//===========用戶級別============
USER_NOT_FOUND(1001002000,"用戶不存在"),
//===========訂單級別============
//===========訂單級別============
;
/**
* 錯誤碼
*/
private int code;
/**
* 錯誤提示
*/
private String message;
ServiceExceptionEnum(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
這裏的返回錯誤的返回格式也基本是錯誤碼code+錯誤提示message,這裏的錯誤碼設計的原則卸載了註釋裏面
下面引入與Service邏輯異常有關的錯誤,這裏選擇的方式還是,封裝通用的返回類
//service中的異常
public final class ServiceException extends RuntimeException{
/**
* 錯誤碼
*/
private final Integer code;
public ServiceException(ServiceExceptionEnum serviceExceptionEnum) {
//使用父類的message字段
super(serviceExceptionEnum.getMessage());
//設置錯誤碼
this.code = serviceExceptionEnum.getCode();
}
public Integer getCode() {
return code;
}
}
這裏後續需要補充各種常見異常類這個坑。
這裏的意思呢,顯然異常類中是有一個message的信息的,然後加上我們自定義的錯誤碼,這裏的錯誤碼呢,會引用我們定義的枚舉類型中的錯誤碼,說實話,寫到這裏,我覺得枚舉類好像也挺好理解的了,就是封裝一連串的final對象,然後就那幾個給定的狀態,比起普通類來說,多了一個枚舉定義的過程。
下一步需要定義一個統一返回的處理器
@ControllerAdvice(basePackages = "com.zzaxg.springboot.controller")
public class GlobalExceptionHandler {
private Logger logger = LoggerFactory.getLogger(getClass());
//使用該異常的code+message屬性,構建CommonResult對象來返回
/**
* 處理ServiceException異常
*
* @param request
* @param ex
* @return
*/
@ResponseBody
@ExceptionHandler(value = ServiceException.class)
public CommonResult serviceExceptionHandler(HttpServletRequest request, ServiceException ex) {
logger.debug("[serviceException]", ex);
//包裝CommonResult結果
return CommonResult.error(ex.getCode(), ex.getMessage());
}
/**
* 處理 MissingServletRequestParameterException 異常
*
* SpringMVC參數不正確
*/
@ResponseBody
@ExceptionHandler(value = MissingServletRequestParameterException.class)
public CommonResult MissingServletRequestParameterException(HttpServletRequest request, MissingServletRequestParameterException ex) {
logger.debug("[missingServletRequestParameterException]", ex);
//包裝CommonResult結果
return CommonResult.error(ServiceExceptionEnum.MISSING_REQUEST_PARAM_ERROR.getCode(), ServiceExceptionEnum.MISSING_REQUEST_PARAM_ERROR.getMessage());
}
//兜底的異常處理
/**
* 處理其他 Exception 異常
*/
@ResponseBody
@ExceptionHandler(value = Exception.class)
public CommonResult exceptionHandler(HttpServletRequest request, Exception e) {
//記錄異常日誌
logger.debug("[exceptionHandler]", e);
//包裝CommonResult結果
return CommonResult.error(ServiceExceptionEnum.SYS_ERROR.getCode(), ServiceExceptionEnum.SYS_ERROR.getMessage());
}
}
同樣是定義了可一個切面,但這裏不需要攔截接口返回結果,所以不需要定義ResponseBodyHandler接口
通過@ExceptionHandler註解定義每個方法對應處理的異常,@ResponseBody註解呢,標記直接使用返回結果作爲API的響應
這裏的logger.debug呢,打印了錯誤日誌
下面寫一個controller進行錯誤的throw
/**
* 測試拋出NullPointerException異常
*
* @return
*/
@GetMapping("/exception-01")
public UserVO exception01() {
throw new NullPointerException("週週不在呢");
}
/**
* 測試拋出ServiceException異常
*
*/
@GetMapping("/exception-02")
public UserVO exception02() {
throw new ServiceException(ServiceExceptionEnum.USER_NOT_FOUND);
}
返回的結果呢,分別是
{
"code": 2001001000,
"message": "服務端發生異常",
"data": null
}
{
"code": 1001002000,
"message": "用戶不存在",
"data": null
}
原文參考芋道源碼
謝謝觀看