文章目錄
- 一、異常處理的核心價值
- 二、核心接口設計
- 三、四大內置實現類源碼解析
- 1. ExceptionHandlerExceptionResolver(現代異常處理核心)
- 2. ResponseStatusExceptionResolver(HTTP狀態碼處理)
- 3. DefaultHandlerExceptionResolver(默認異常轉換)
- 4. SimpleMappingExceptionResolver(傳統配置方式)
- 四、異常處理的責任鏈模式
- 五、@ControllerAdvice的深層機制
- 1. 全局異常處理原理
- 2. 異常匹配算法
- 六、統一異常處理最佳實踐
- 1. 標準化錯誤響應
- 2. 業務異常體系設計
- 3. 參數驗證異常處理
- 七、生產環境高級配置
- 1. 異常處理監控
- 2. 動態異常配置
- 3. 微服務異常傳播
- 八、設計思想總結
本文是Spring MVC九大組件解析系列第六篇,我們將深入探索Spring MVC的異常處理機制,揭開
@ControllerAdvice
和@ExceptionHandler
的實現原理,分析異常解析的責任鏈模式,并構建統一的異常處理體系。Spring MVC整體設計核心解密參閱:Spring MVC設計精粹:源碼級架構解析與實踐指南
一、異常處理的核心價值
在Web應用中,優雅的異常處理是保障系統健壯性的關鍵:
- 用戶體驗:向用戶提供友好的錯誤提示,而非晦澀的堆棧信息
- 系統可維護性:統一異常格式,便于日志收集和問題排查
- 業務分離:將異常處理邏輯從業務代碼中解耦,保持代碼整潔
Spring MVC通過HandlerExceptionResolver
組件實現三大核心功能:
- 異常轉換:將Java異常轉換為統一的錯誤響應
- 異常分類:根據不同異常類型采取不同處理策略
- 異常恢復:在異常發生后盡可能恢復系統狀態
二、核心接口設計
源碼位置:org.springframework.web.servlet.HandlerExceptionResolver
核心源碼:
設計哲學:通過責任鏈模式實現異常處理的解耦和擴展。
三、四大內置實現類源碼解析
1. ExceptionHandlerExceptionResolver(現代異常處理核心)
源碼位置:org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver
支持注解:@ExceptionHandler
和@ControllerAdvice
啟動階段:注解掃描與注冊
運行時:異常匹配與處理
2. ResponseStatusExceptionResolver(HTTP狀態碼處理)
源碼位置:org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver
支持注解:@ResponseStatus
和ResponseStatusException
核心源碼:
3. DefaultHandlerExceptionResolver(默認異常轉換)
源碼位置:org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
主要功能:將Spring MVC內部異常轉換為合適的HTTP狀態碼
核心源碼:
4. SimpleMappingExceptionResolver(傳統配置方式)
源碼位置:org.springframework.web.servlet.handler.SimpleMappingExceptionResolver
主要功能:通過配置文件映射異常到視圖
核心源碼:
配置示例:
@Bean
public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();Properties mappings = new Properties();mappings.setProperty("java.lang.Exception", "error/generic");mappings.setProperty("java.io.IOException", "error/io");resolver.setExceptionMappings(mappings);resolver.setDefaultErrorView("error/default");return resolver;
}
四、異常處理的責任鏈模式
Spring MVC通過責任鏈模式組織多個ExceptionResolver
:
配置順序決定了解析優先級:
// 通過Order接口控制解析順序
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public ExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver() {return new ExceptionHandlerExceptionResolver();
}@Bean
@Order(Ordered.LOWEST_PRECEDENCE)
public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {return new SimpleMappingExceptionResolver();
}
五、@ControllerAdvice的深層機制
1. 全局異常處理原理
@ControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)public ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex) {ErrorResponse error = new ErrorResponse("系統錯誤", ex.getMessage());return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);}@ExceptionHandler(UserNotFoundException.class)public ResponseEntity<ErrorResponse> handleUserNotFound(UserNotFoundException ex) {ErrorResponse error = new ErrorResponse("用戶不存在", ex.getMessage());return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);}
}
2. 異常匹配算法
關鍵源碼:
六、統一異常處理最佳實踐
1. 標準化錯誤響應
// 統一錯誤響應體
public class ErrorResponse {private String code; // 錯誤代碼private String message; // 用戶可見消息private String detail; // 開發調試詳情private long timestamp; // 時間戳private String path; // 請求路徑// 構造方法等
}// 異常處理器
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception ex, WebRequest request) {ErrorResponse error = ErrorResponse.builder().code("INTERNAL_ERROR").message("系統內部錯誤").detail(ex.getMessage()).path(request.getDescription(false)).timestamp(System.currentTimeMillis()).build();return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
2. 業務異常體系設計
// 基礎業務異常
public abstract class BusinessException extends RuntimeException {private final String errorCode;public BusinessException(String errorCode, String message) {super(message);this.errorCode = errorCode;}public String getErrorCode() { return errorCode; }
}// 具體業務異常
public class UserNotFoundException extends BusinessException {public UserNotFoundException(Long userId) {super("USER_NOT_FOUND", "用戶不存在: " + userId);}
}// 統一處理業務異常
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex) {ErrorResponse error = new ErrorResponse(ex.getErrorCode(), ex.getMessage());return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
}
3. 參數驗證異常處理
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidationException(MethodArgumentNotValidException ex) {List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();List<String> errors = fieldErrors.stream().map(error -> error.getField() + ": " + error.getDefaultMessage()).collect(Collectors.toList());ErrorResponse error = new ErrorResponse("VALIDATION_FAILED", "參數驗證失敗", errors);return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
}
七、生產環境高級配置
1. 異常處理監控
@Component
public class ExceptionMonitoringAspect {@Autowiredprivate MeterRegistry meterRegistry;@AfterThrowing(pointcut = "within(@org.springframework.web.bind.annotation.RestController *)", throwing = "ex")public void monitorException(Exception ex) {// 記錄異常指標meterRegistry.counter("exception.count", "type", ex.getClass().getSimpleName(),"handler", "ExceptionHandler").increment();// 發送告警(重要異常)if (ex instanceof CriticalBusinessException) {alertService.sendAlert(new ExceptionAlert(ex));}}
}
2. 動態異常配置
@Configuration
public class DynamicExceptionConfig {@Beanpublic SimpleMappingExceptionResolver dynamicExceptionResolver() {DynamicExceptionResolver resolver = new DynamicExceptionResolver();resolver.setExceptionMappings(loadExceptionMappingsFromDatabase());resolver.setWarnLogCategory(DynamicExceptionResolver.class.getName());return resolver;}private Properties loadExceptionMappingsFromDatabase() {// 從數據庫加載異常映射配置Properties mappings = new Properties();exceptionConfigRepository.findAll().forEach(config -> mappings.setProperty(config.getExceptionClass(), config.getViewName()));return mappings;}
}
3. 微服務異常傳播
// 跨服務異常響應體
public class ServiceErrorResponse {private String serviceName;private String traceId;private ErrorResponse error;// 構造方法等
}// 全局異常處理器(微服務版)
@ExceptionHandler(Exception.class)
public ResponseEntity<ServiceErrorResponse> handleMicroserviceException(Exception ex, HttpServletRequest request) {// 獲取分布式追蹤IDString traceId = (String) request.getAttribute("X-Trace-Id");ServiceErrorResponse serviceError = new ServiceErrorResponse("user-service", traceId, convertToErrorResponse(ex));return ResponseEntity.status(determineHttpStatus(ex)).header("X-Trace-Id", traceId).body(serviceError);
}
八、設計思想總結
- 責任鏈模式
多個ExceptionResolver組成處理鏈,各司其職 - 注解驅動
@ExceptionHandler
和@ControllerAdvice
提供聲明式異常處理 - 分層處理
從具體異常到通用異常的逐級fallback機制 - 統一抽象
標準化錯誤響應格式,提升系統可維護性 - 可擴展架構
支持自定義ExceptionResolver滿足特殊需求
下一篇預告:
九大組件源碼剖析(七):ViewResolver - 視圖解析的智慧
我們將深入分析視圖解析機制,探索模板引擎集成原理,以及如何實現多視圖技術統一抽象。
思考題:在微服務架構下,如何設計跨服務的異常處理適配器,實現異常信息的標準化和跨服務傳播?