基于spring boot實現(xiàn)一個全局異常處理器
還記得前面我們的實現(xiàn)邏輯,在service層如果有校驗失敗我們會拋出異常,而controller中我們對其并沒有處理,實際上spring boot有自己全局的錯誤處理形式。我們可以基于spring boot提供的切面特性,來很輕松的實現(xiàn)全局異常的處理,現(xiàn)在我們約定,只要后臺邏輯處理失敗的情況,我們都將拋出異常,包括controller中的處理邏輯。
實現(xiàn)全局異常處理器
現(xiàn)在我們就來編寫全局異常處理器。
package com.xiaojuan.boot.common.web.support;
import ...
import static com.xiaojuan.boot.common.enums.BusinessError.*;
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
/** 維護一個錯誤碼與http狀態(tài)碼的映射 */
private Map<Integer, HttpStatus> httpStatusMap;
@PostConstruct
private void init() {
httpStatusMap = new HashMap<>();
httpStatusMap.put(NO_LOGIN.getValue(), HttpStatus.UNAUTHORIZED);
httpStatusMap.put(HAS_NO_ROLE.getValue(), HttpStatus.FORBIDDEN);
}
@ExceptionHandler(BusinessException.class)
public ResponseEntity<Response<?>> handleException(BusinessException ex) {
log.error(ex.getMessage(), ex);
// 默認服務器端錯誤,返回500狀態(tài)碼
HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
if (!StringUtils.isEmpty(ex.getErrCode()) && httpStatusMap.containsKey(ex.getErrCode())) {
status = httpStatusMap.get(ex.getErrCode());
}
return ResponseEntity.status(status).body(Response.fail(ex.getMessage(), ex.getErrCode(), ex.getData()));
}
@ExceptionHandler(Exception.class)
public ResponseEntity<Response<?>> handleException(Exception ex) {
log.error(ex.getMessage(), ex);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(Response.fail("小卷生鮮電商系統(tǒng)異常:" + ex.getMessage()));
}
}代碼詳解
這里我們用了@RestControllerAdvice注解對所有的@RestController修飾的controller都進行攔截,只要拋出了異常,就交給這個處理器來處理。
這里要說下響應的http狀態(tài)碼,一般都返回200,某些情況下我們將返回一個可以讓前端特別處理的狀態(tài)碼,比如用戶未登錄的請求被攔截了我們可以返回401,用戶登錄了卻沒有權(quán)限的操作,我們返回403,這樣前端對這塊直接從http狀態(tài)就能識別請求結(jié)果的狀態(tài)。而對于我們業(yè)務開發(fā)來說,關(guān)注的是業(yè)務處理的錯誤碼,在這里我們和請求http狀態(tài)碼之間做了一個映射轉(zhuǎn)換,維護在httpStatusMap成員變量中。
接下來,我們寫了兩個異常處理方法,它們都必須用@ExceptionHandler注解來指定我們要處理的異常的類型,這里我們只考慮兩種異常:我們自定義的業(yè)務異常BusinessException和最大的Exception。
對于BusinessException,我們要考慮HttpStatus的判斷邏輯,如果我們將某些業(yè)務錯誤碼和http狀態(tài)碼做了映射,那么對于這些業(yè)務錯誤碼我們就取映射到的http狀態(tài)碼來返回,否則我們返回服務器端錯誤的500狀態(tài)碼。
注意處理方法最后的返回結(jié)果,我們使用的是ResponseEntity<Response<?>>,spring web模塊提供的ResponseEntity可以幫助我們按照指定的http狀態(tài)碼并解析指定格式的內(nèi)容體(Spring Boot默認配置json形式)進行前端響應。而要響應的對象就是我們之前定義的Response,只不過我們將字段errCode的類型從原來的String改成了Integer,因為業(yè)務錯誤碼我們就定義為數(shù)值型,同樣的還有BusinessException類中的errCode字段類型的調(diào)整。
除了BusinessException,我們只處理最大的Exception,http狀態(tài)碼固定為500,錯誤消息也統(tǒng)一以固定的形式開頭。
錯誤碼枚舉類
將應用中業(yè)務錯誤碼我們定義在一個枚舉中進行維護:
package com.xiaojuan.boot.common.enums;
import ...
@Getter
@AllArgsConstructor
public enum BusinessError {
PARAM_INVALID("參數(shù)校驗失敗", 10001),
RECORD_EXISTS("后臺記錄已存在", 10002),
HAS_NO_ROLE("用戶未授權(quán),不能訪問", 403),
NO_LOGIN("請先登錄再操作", 401);
private final String label;
private final Integer value;
}這里我們給出默認的說明,一般在拋出業(yè)務異常時我們可以指定更具體的錯誤,而不會使用這里默認的錯誤消息。
service層拋出異常調(diào)整
現(xiàn)在我們對service層拋出異常做下調(diào)整,一般我們只要傳入錯誤信息來構(gòu)造BusinessException。有些時候我們還可以傳入錯誤碼來進一步區(qū)分這些錯誤。


實現(xiàn)自己的Assert工具
既然我們先前定義了自己的BusinessException,并且在其中維護了業(yè)務錯誤碼errCode,就沒必要用spring的Assert工具了,因為它拋出來的是IllegalStateException異常,最終被我們?nèi)之惓L幚砥饕宰畲蟮?code>Exception的處理邏輯進行包裝響應結(jié)果,自然“參數(shù)校驗失敗”的錯誤碼類型就丟了,因此這里我們基于spring對Assert的實現(xiàn),我們包裝為自己的Assert:
package com.xiaojuan.boot.util;
import ...
public class Assert {
public static void hasText(@Nullable String text, String message) {
if (!StringUtils.hasText(text)) {
throw new BusinessException(message, BusinessError.PARAM_INVALID.getValue());
}
}
}controller層拋出異常
最后我們將原來預留todo注釋的地方改為拋出異常的形式:

最后,我們再基于test.http對拋出異常的測試場景進行測試,看是否達到預期的http狀態(tài)碼和json結(jié)構(gòu),這個大家自行測試。
到此這篇關(guān)于基于spring boot實現(xiàn)一個全局異常處理器的文章就介紹到這了,更多相關(guān)spring boot全局異常處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java批量插入數(shù)據(jù)的代碼實現(xiàn)
日常工作或者學習中,可能會遇到批量插入數(shù)據(jù)的需求,一般情況下數(shù)據(jù)量少的時候,我們會直接調(diào)用批量接口插入數(shù)據(jù)即可,當數(shù)據(jù)量特別大時,我們就會用到分批插入數(shù)據(jù),所以本文給大家介紹了Java批量插入數(shù)據(jù)的代碼實現(xiàn),需要的朋友可以參考下2024-01-01
springmvc實現(xiàn)導出數(shù)據(jù)信息為excle表格示例代碼
本篇文章主要介紹了springmvc實現(xiàn)導出數(shù)據(jù)信息為excle表格,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧。2017-01-01
基于Jenkins搭建.NET FrameWork持續(xù)集成環(huán)境
這篇文章主要介紹了基于Jenkins搭建.NET FrameWork持續(xù)集成環(huán)境,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-08-08
IDEA下Maven的pom文件導入依賴出現(xiàn)Auto build completed with errors的問題
這篇文章主要介紹了IDEA下Maven的pom文件導入依賴出現(xiàn)Auto build completed with errors,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06

