Spring MVC 九大組件源碼深度剖析(六):HandlerExceptionResolver - 異常處理的藝術

文章目錄

    • 一、異常處理的核心價值
    • 二、核心接口設計
    • 三、四大內置實現類源碼解析
      • 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組件實現三大核心功能:

  1. 異常轉換:將Java異常轉換為統一的錯誤響應
  2. 異常分類:根據不同異常類型采取不同處理策略
  3. 異常恢復:在異常發生后盡可能恢復系統狀態

二、核心接口設計

源碼位置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
支持注解@ResponseStatusResponseStatusException
核心源碼
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

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);
}

八、設計思想總結

  1. 責任鏈模式
    多個ExceptionResolver組成處理鏈,各司其職
  2. 注解驅動
    @ExceptionHandler@ControllerAdvice提供聲明式異常處理
  3. 分層處理
    從具體異常到通用異常的逐級fallback機制
  4. 統一抽象
    標準化錯誤響應格式,提升系統可維護性
  5. 可擴展架構
    支持自定義ExceptionResolver滿足特殊需求

下一篇預告:
九大組件源碼剖析(七):ViewResolver - 視圖解析的智慧
我們將深入分析視圖解析機制,探索模板引擎集成原理,以及如何實現多視圖技術統一抽象。


思考題:在微服務架構下,如何設計跨服務的異常處理適配器,實現異常信息的標準化和跨服務傳播?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/920773.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/920773.shtml
英文地址,請注明出處:http://en.pswp.cn/news/920773.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MCP(Model Context Protocol,模型上下文協議)介紹

1. 背景 隨著大語言模型&#xff08;LLM, Large Language Model&#xff09;的應用越來越廣泛&#xff0c;一個核心問題逐漸凸顯&#xff1a; 模型在對話或推理時&#xff0c;往往只能依賴有限上下文窗口。外部工具、知識庫、應用接口如何統一接入模型&#xff0c;缺乏標準協議…

synchronized的鎖對象 和 wait,notify的調用者之間的關系

誰調用了wait和notify方法&#xff0c;會決定這兩個方法的控制范圍嗎&#xff1f;你的問題非常深入&#xff0c;涉及到 wait() 和 notify() 方法的控制范圍和作用域。讓我們詳細分析一下&#xff1a;? 核心概念&#xff1a;控制范圍由“鎖對象”決定wait() 和 notify() 的控制…

【技術教程】如何將文檔編輯器集成到用 .Net 編寫的網絡應用程序中

在現代網絡應用中&#xff0c;?富文本編輯能力已成為內容管理系統的核心需求。對于 .NET 開發者而言&#xff0c;選擇適合的編輯器并高效集成&#xff0c;是構建企業級應用的關鍵一步&#xff0c;可讓項目管理、 CRM 或定制化系統具備原生辦公能力&#xff0c;消除頻繁切換應用…

【大模型記憶-Mem0詳解-1】概述

目的和能力 Mem0 通過提供以下功能將無狀態 AI 應用程序轉換為有狀態、支持內存的系統&#xff1a; 持久記憶 &#xff1a;跨會話長期保留用戶偏好、對話歷史記錄和上下文信息多級內存 &#xff1a;支持具有自適應個性化的用戶級、會話級和代理級內存智能提取 &#xff1a;基于…

2024年山東省信息學小學組(CSP-X)第一輪題解

2024年山東省信息學小學組(CSP-X)第一輪題解 原題下載 單項選擇題 閱讀程序 閱讀程序 #1 判斷題 閱讀程序 #2 判斷題 單選題 閱讀程序 #3 判斷題 單選題 完善程序 消滅怪獸 位運算操作 原題下載 CSP-X2024小學組(山東)第一輪試題以及答案 單項選擇題 共 15 題,每題 2 分…

SW - 用裝配圖的方式組合多個子零件然后轉換成為零件,可維護性好

文章目錄SW - 用裝配圖的方式組合多個子零件然后轉換成為零件&#xff0c;可維護性好概述筆記例子將裝配圖另存為零件將零件圖中的多個實體組合為一個實體的特征備注ENDSW - 用裝配圖的方式組合多個子零件然后轉換成為零件&#xff0c;可維護性好 概述 以前畫機械零件&#x…

PhotoshopImageGenerator:基于Photoshop的自動化圖像數據集生成工具

整體邏輯與設計思路 PhotoshopImageGenerator是一個基于Python和Win32COM的自動化工具,通過控制Adobe Photoshop CC 2019創建多樣化的圖像數據集。其核心設計思路是通過程序化調用Photoshop的圖像編輯能力,為基礎圖像添加隨機元素(圖片、文本、形狀)和效果,快速生成大量變…

macos自動安裝emsdk4.0.13腳本

1.替換文件 emsdk #!/bin/sh # Copyright 2019 The Emscripten Authors. All rights reserved. # Emscripten is available under two separate licenses, the MIT license and the # University of Illinois/NCSA Open Source License. Both these licenses can be # foun…

c++ Effective c++ 條款5

class MyClass { public:MyClass(int& ref, const int c_val) : myRef(ref), myConstVal(c_val) {}// 明確刪除拷貝操作MyClass(const MyClass&) delete;MyClass& operator(const MyClass&) delete;private:int& myRef; // 引用成員const int myCo…

如何使用 Xshell 8 連接到一臺 CentOS 7 電腦(服務器)

什么是 Xshell&#xff1f; Xshell 是一款功能強大的、適用于 Windows 平臺的終端模擬器。它支持 SSH (Secure Shell)、SFTP、TELNET、RLOGIN 和 SERIAL 等多種網絡協議&#xff0c;讓用戶能夠安全地連接和管理遠程服務器。 對于開發者、系統管理員和網絡工程師來說&#xff…

CSS scale函數詳解

目錄 基本語法 核心特性 常用場景示例 1. 等比例縮放&#xff08;X 軸和 Y 軸相同&#xff09; 2. 非等比例縮放&#xff08;X 軸和 Y 軸不同&#xff09; 3. 翻轉并縮放 4. 配合過渡動畫實現交互效果 5. 圖片懸停縮放效果 6. 縮放原點調整 與其他變換組合使用 注意…

【MATLAB代碼】基于EKF的二維組合導航仿真代碼,狀態量為位置、速度、航向角與IMU偏置,觀測量為XY軸的位置和速度,附完整代碼

8維狀態量(2維位置、2維速度、航向角、航向角偏置、2維加速度計偏置)+4維觀測量(2維位置、2維速度)。 訂閱專欄后,可直接查看源代碼,粘貼到MATLAB空腳本中即可直接運行、得到結果 文章目錄 運行結果 MATLAB源代碼 程序詳解 ?? 程序概述 狀態預測(狀態轉移函數) 狀態雅…

OpenCV 圖像輪廓檢測

目錄 一、輪廓檢測基礎概念 二、核心 API 詳解&#xff1a;cv2.findContours () 參數說明&#xff1a; 返回值說明&#xff1a; 三、輪廓檢測實戰步驟 1. 圖像預處理&#xff08;灰度化與二值化&#xff09; 2. 查找輪廓 3. 繪制輪廓 四、輪廓的常用屬性與操作 1. 輪…

【圖論】 Graph.jl 概覽

文章目錄安裝基礎使用基本操作全局圖的指標頂點性質邊性質讀寫圖按照 .lgz 格式存儲圖數據&#xff08;壓縮格式&#xff09;按照 .lg 格式存儲圖數據&#xff08;非壓縮格式&#xff09;圖的繪制TikzGraphs.jl Latex 論文風格GraphPlot.jl 通常與 Compose.jl 一起使用SGtSNEpi…

[java] 控制三個線程按順序交替輸出數字123123…

控制三個線程按順序交替輸出數字123123… synchronized&#xff08;配合專用鎖對象&#xff09; 通過共享鎖和 volatile 變量控制執行順序&#xff0c;每個線程按指定順序打印指定內容&#xff0c;確保輸出序列如 “123123…”。使用 synchronized 和 wait/notifyAll 實現線程間…

[C#]winform基于yolov8-seg實現的指甲分割實現源碼

【測試環境】 vs2019 net framework4.7.2 onnxruntime1.16.3 opencvsharp 注意源碼運行在CPU上不支持GPU運行&#xff0c;由于net framework限制GPU會很慢因此沒有GPU版本提供。 【運行步驟】 打開sln項目 選擇x64 debug運行即可 如需要再x64 release運行可以將x64 debu…

數據結構——線性表(鏈表,力扣中等篇,增刪查改)

文章目錄一、增刪查改1.1增&#xff08;插入節點&#xff09;1.1.1兩數后插入公約數1.1.2循環有序鏈表的插入1.2刪&#xff08;移除節點&#xff09;1.2.1刪除已知的node節點【交換val值】1.2.2移除數組中已存在的節點【unordered_set】1.2.3刪除和為0的節點【前綴和】1.3改&am…

【Android】OkHttp發起GET請求 POST請求

三三要成為安卓糕手 一&#xff1a;OkHttp介紹 OkHttp 是一個開源的、強大且高效的 HTTP 客戶端庫&#xff0c;主要用于在 Java后端和Android 項目中進行網絡請求。 //在gradle中添加依賴 com.squareup.okhttp3:okhttp:4.12.0二&#xff1a;GET請求/*** 使用OkHttp發起get請求*…

[Mysql數據庫] 知識點總結8

1. 請詳細描述在復制拓撲中參與復制的線程類型以及各自所承擔的功能。答&#xff1a;當從屬服務器連接到主服務器時&#xff0c;在主服務器上會創建 Binlog 轉儲線程&#xff0c;在從屬服務器上會默 認創建 I/O 線程和 SQL 線程。- Binlog 轉儲線程用于從二進制日志讀取事件并將…

250829-Gitlab數據備份與恢復

下面給你一份可落地的遷移方案&#xff0c;保證 GitLab 的數據和配置完整遷移到服務器 B。你當前用的是 GitLab Omnibus&#xff08;docker 版&#xff09;&#xff0c;數據都在你映射的 3 個目錄里&#xff08;/etc/gitlab, /var/log/gitlab, /var/opt/gitlab&#xff09;&…