基於Spring Boot的統一異常處理設計
作者: Grey
原文地址:https://www.cnblogs.com/greyzeng/p/11733327.html
Spring Boot中,支持RestControllerAdvice統一處理異常,在一個請求響應周期當中,如果Controller,Service,Repository出現任何異常,都會被RestControllerAdvice機制所捕獲,進行統一處理。
進行統一異常處理的目的也就是為了將千奇百怪的異常信息轉換成用戶可識別的錯誤信息
統一異常攔截器
@RestControllerAdvice
@Slf4j
public class GlobalExceptionTranslator {
}
系統中的兩類異常處理
第一類:業務自定義的異常,遇到這種異常,攔截器記錄后,將業務異常自己的信息拋出。
@ExceptionHandler(BusinessException.class)
public JSONObject handleError(BusinessException e) {
log.error("Business Exception {}", getStackTraceAsString(e));
return error(e);
}
第二類:未定義異常,攔截器負責統一屏蔽原來的異常信息,轉為服務器內部異常拋出。
@ExceptionHandler(Throwable.class)
public JSONObject handleError(Throwable undefined) {
log.error("Internal Server Error {}", getStackTraceAsString(undefined));
return error(new BusinessException(FAILURE));
}
調用者收到error的結果后,直接顯示msg內容為用戶可見的錯誤信息即可。
如何自定義一個業務異常
在業務開發中,通常無需進行Try catch處理,有業務異常直接拋出即可。如果需要定義一類通用的異常,則需要在自己業務模塊下新建異常類,繼承於 BusinessException
public class PaymentException extends BusinessException {
//重寫構造函數,從而定義該自定義異常的用戶可見的錯誤信息
public PaymentException() {
super("支付失敗");
}
}
如何自定義一個框架級異常
在系統框架層面,已經預定義了一些常見的異常類,如:
類名 | 定義 | 預置錯誤信息 |
---|---|---|
PermissionDenyException | 用戶訪問未授權的內容 | 權限不足 |
ServiceNotFoundException | 調用微服務失敗 | 調用相關服務失敗 |
其他異常 | ... | ... |
在定義框架級異常時,除了需要編寫異常類之外,如需要前端根據error CODE做對應的處理,就可以在ResultCode中增加定義。示例如下:
@Getter
@AllArgsConstructor
public enum ResultCode {
/**
* 操作成功
*/
SUCCESS(HTTP_OK, "操作成功"),
/**
* 因程序內部錯誤操作失敗(如不指定,則默認這個異常)
*/
FAILURE(HTTP_INTERNAL_ERROR, "系統運行異常,請聯系管理員"),
/**
* 用戶訪問未授權的內容
*/
UN_AUTHORIZED(HTTP_UNAUTHORIZED, "權限不足"),
/**
* 調用微服務失敗
*/
NOT_FOUND(HTTP_NOT_FOUND, "調用相關服務失敗");
final int code;
final String msg;
}
一個框架級異常的實現類
public class PermissionDenyException extends BusinessException {
public PermissionDenyException() {
super(UN_AUTHORIZED);
}
}
如需要框架對該異常定義統一的策略,則需要在GlobalExceptionTranslator實現該策略,示例如下:
public class GlobalExceptionTranslator {
@ExceptionHandler(NewGlobalException.class)
public JSONObject handleError(NewGlobalException e) {
// 這里可以實現自定義的異常策略
return error(new BusinessException(e.getResultCode(),e.getMessage()));
}
}