文章目录

    • 一、异常处理的核心价值
    • 二、核心接口设计
    • 三、四大内置实现类源码解析
      • 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;&…