JAVA中Spring全局异常处理@ControllerAdvice解析

一、@ControllerAdvice基础概念

1. 什么是@ControllerAdvice?

@ControllerAdvice是Spring 3.2引入的注解,用于定义全局控制器增强组件,主要功能包括:

  • 全局异常处理(最常用)
  • 全局数据绑定
  • 全局数据预处理

2. 核心作用

  • 集中处理控制器层异常
  • 避免重复的异常处理代码
  • 统一API错误响应格式
  • 减少try-catch块污染业务代码

二、基础全局异常处理实现

1. 最小实现示例

@ControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)@ResponseBodypublic ResponseEntity<ErrorResponse> handleException(Exception ex) {ErrorResponse error = new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(),"服务器内部错误",ex.getMessage());return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);}
}// 统一错误响应DTO
@Data
@AllArgsConstructor
class ErrorResponse {private int status;private String error;private String message;private long timestamp = System.currentTimeMillis();
}

2. 处理特定异常

@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleResourceNotFound(ResourceNotFoundException ex) {ErrorResponse error = new ErrorResponse(HttpStatus.NOT_FOUND.value(),"资源未找到",ex.getMessage());return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}

三、高级配置技巧

1. 限定控制器范围

// 只处理指定包下的控制器
@ControllerAdvice(basePackages = "com.example.web.controllers")// 只处理带有特定注解的控制器
@ControllerAdvice(annotations = RestController.class)// 只处理指定类
@ControllerAdvice(assignableTypes = {UserController.class, ProductController.class})

2. 异常处理优先级

Spring会按照最具体到最通用的顺序匹配@ExceptionHandler

@ExceptionHandler(FileUploadException.class)  // 优先匹配
public ResponseEntity<?> handleFileUpload(FileUploadException ex) { ... }@ExceptionHandler(IOException.class)          // 次级匹配
public ResponseEntity<?> handleIO(IOException ex) { ... }@ExceptionHandler(Exception.class)            // 兜底处理
public ResponseEntity<?> handleGeneral(Exception ex) { ... }

3. 获取请求上下文

通过注入请求对象获取更多信息:

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception ex, WebRequest request) {String path = ((ServletWebRequest)request).getRequest().getRequestURI();ErrorResponse error = new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(),"处理请求[" + path + "]时发生错误",ex.getMessage());return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}

四、常见异常处理模式

1. 业务异常处理

@ExceptionHandler(BusinessException.class)
public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex) {ErrorResponse error = new ErrorResponse(ex.getErrorCode(),ex.getErrorType(),ex.getMessage());return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}

2. 数据校验异常

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidationException(MethodArgumentNotValidException ex) {List<String> errors = ex.getBindingResult().getFieldErrors().stream().map(FieldError::getDefaultMessage).collect(Collectors.toList());ErrorResponse error = new ErrorResponse(HttpStatus.BAD_REQUEST.value(),"参数校验失败",errors.toString());return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}

3. 认证授权异常

@ExceptionHandler({AccessDeniedException.class,AuthenticationException.class
})
public ResponseEntity<ErrorResponse> handleAuthException(RuntimeException ex) {HttpStatus status = ex instanceof AccessDeniedException ? HttpStatus.FORBIDDEN : HttpStatus.UNAUTHORIZED;ErrorResponse error = new ErrorResponse(status.value(),"权限不足",ex.getMessage());return new ResponseEntity<>(error, status);
}

五、最佳实践建议

1. 异常分类处理

建议将异常分为几大类分别处理:

异常类型处理方式HTTP状态码
业务异常返回具体错误信息400-499
系统异常记录日志,返回通用错误500
第三方服务异常记录日志,返回服务不可用503
参数校验异常返回详细校验错误400

2. 日志记录策略

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception ex, HttpServletRequest request) {log.error("请求[{} {}]处理失败", request.getMethod(), request.getRequestURI(), ex);// ...返回错误响应
}

3. 生产环境与开发环境差异

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception ex,Environment env) {boolean isProd = Arrays.asList(env.getActiveProfiles()).contains("prod");String message = isProd ? "服务器错误,请联系管理员" : ex.getMessage();// ...返回错误响应
}

六、原理深度解析

1. 实现原理

@ControllerAdvice的工作原理:

  1. 通过@ControllerAdvice标记的类会被ExceptionHandlerExceptionResolver识别
  2. Spring初始化时会收集所有@ExceptionHandler方法
  3. 当控制器抛出异常时,DispatcherServlet会:
    • 查找当前控制器内的@ExceptionHandler方法
    • 如果没有,则查找@ControllerAdvice中的处理方法
    • 按异常类型匹配最具体的方法

2. 核心组件协作

[DispatcherServlet]|v
[HandlerExceptionResolver]||-- [ExceptionHandlerExceptionResolver] (处理@ExceptionHandler)|-- [ResponseStatusExceptionResolver] (处理@ResponseStatus)`-- [DefaultHandlerExceptionResolver] (处理Spring标准异常)

3. 执行顺序

  1. @ExceptionHandler方法(当前控制器内)
  2. @ControllerAdvice中的@ExceptionHandler方法
  3. @ResponseStatus异常
  4. Spring默认异常处理

七、常见问题解决方案

1. 异常处理不生效

可能原因:

  • 未启用注解驱动:确保配置了@EnableWebMvc<mvc:annotation-driven/>
  • 包扫描问题:@ControllerAdvice类未被Spring管理
  • 异常被捕获:上游代码已经catch了异常

2. 处理多个相同类型异常

@ExceptionHandler({IllegalArgumentException.class, IllegalStateException.class})
public ResponseEntity<?> handleIllegal(RuntimeException ex) {// 统一处理多种相似异常
}

3. 自定义异常解析器

如需更复杂控制,可以实现HandlerExceptionResolver

@Component
public class CustomExceptionResolver implements HandlerExceptionResolver {@Overridepublic ModelAndView resolveException(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex) {// 自定义异常处理逻辑return ...;}
}

八、Spring Boot增强支持

1. 错误属性配置

application.properties:

server.error.include-message=always
server.error.include-stacktrace=on_param
server.error.include-binding-errors=always

2. 自定义ErrorController

@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class CustomErrorController implements ErrorController {@RequestMappingpublic ResponseEntity<ErrorResponse> handleError(HttpServletRequest request) {HttpStatus status = getStatus(request);ErrorResponse error = new ErrorResponse(status.value(),"自定义错误处理",(String)request.getAttribute("javax.servlet.error.message"));return new ResponseEntity<>(error, status);}private HttpStatus getStatus(HttpServletRequest request) {Integer code = (Integer) request.getAttribute("javax.servlet.error.status_code");return code != null ? HttpStatus.valueOf(code) : HttpStatus.INTERNAL_SERVER_ERROR;}
}

九、性能优化建议

  1. 减少@ControllerAdvice扫描范围:精确指定basePackages
  2. 避免在异常处理中进行IO操作:如数据库写入
  3. 使用响应缓存:对相同异常返回缓存响应
  4. 异步异常处理:对耗时处理使用@Async
@ExceptionHandler(ReportableException.class)
@Async
public CompletableFuture<ResponseEntity<?>> handleReportable(ReportableException ex) {// 异步处理可报告异常reportService.sendReport(ex);return CompletableFuture.completedFuture(ResponseEntity.badRequest().build());
}

通过合理使用@ControllerAdvice进行全局异常处理,可以显著提高Spring应用的健壮性和可维护性,同时为客户端提供一致的错误响应格式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/903414.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开放平台架构方案- GraphQL 详细解释

GraphQL 详细解释 GraphQL 是一种用于 API 的查询语言&#xff0c;由 Facebook 开发并开源&#xff0c;旨在提供一种更高效、灵活且强大的数据获取和操作方式。它与传统的 REST API 有显著不同&#xff0c;通过类型系统和灵活的查询能力&#xff0c;解决了 REST 中常见的过度获…

labview项目文件架构

为了使 LabVIEW 项目更具可扩展性和易于维护&#xff0c;合理规划和设计项目文件结构是非常重要的。 以下是一些基于行业经验和最佳实践的建议&#xff1a; 1. ### 文件夹层次划分 将不同的功能模块分开存储在一个清晰的分层目录结构中是一个常见的做法。通常情况下&#xff…

Chrome的插件扩展程序安装目录是什么?在哪个文件夹?

目录 前提 直接复制到浏览器中打开 Mac下Chrome extension 安装路径 最近换了mac pro用起来虽然方便&#xff0c;但是对常用的一些使用方法还是不熟悉。这不为了找到mac上chrome插件的安装路径在哪里&#xff0c;花费了不少时间。我想应用有不少像小编一样刚刚使用mac的小白…

第13讲:图形尺寸与分辨率设置——适配论文版面,打造专业图稿!

目录 📌 为什么这一讲重要? 🎯 一、先认识几个关键词 ✍️ 二、ggsave() 是导出图的标准方法 📐 三、尺寸设置技巧:对齐目标期刊 🔍 找到目标期刊的图形栏宽 📦 四、多个图组合导出(与 patchwork 搭配) 🧪 五、使用 Cairo / ragg 导出高质量图 🎁 六…

2025年- H13-Lc120-189.轮转数组(普通数组)---java版

1.题目描述 2.思路 import java.util.Arrays;public class H189 {public static void main(String[] args) {int[] newArr {1, 2, 3, 4, 5};int[] nums new int[5];System.arraycopy(newArr,0,nums,0,4);System.out.println(Arrays.toString(nums)); } }补充2&#xff1a; 3.…

机器人--相机

教程 畸变和校正 单目和双目标定 单双&#xff0c;rgb-d原理 单目相机 只有一个摄像头的相机。 原理 小孔成像。 缺点 单目相机无法测量物体点的深度信。 因为物体的Z轴坐标系无法测量。 双目相机 有两个摄像头的相机。 用两个单目相机组成的双目相机就可以测量深度信…

Go 语言入门:(一) 环境安装

一、前言 这里不同于其他人的 Go 语言入门&#xff0c;环境安装我向来注重配置&#xff0c;比如依赖包、缓存的默认目录。因为前期不弄好&#xff0c;后面要整理又影响这影响那的&#xff0c;所以就干脆写成文章&#xff0c;方便后期捡起。 二、安装 1. 安装包 https://go.…

笔试专题(十二)

文章目录 主持人调度题解代码 小红的ABC题解代码 不相邻取数题解代码 空调遥控题解代码 主持人调度 题目链接 题解 1. 排序 2. 先按左端点的大小进行排序&#xff0c;保证时间是连续的&#xff0c;如果后一个点的左端点大于等于前一个点的右端点就是和法的&#xff0c;否则…

Ansible 守护 Windows 安全(Ansible Safeguards Windows Security)

Ansible 守护 Windows 安全&#xff1a;自动化基线检查与加固 在当今网络威胁日益严峻的形势下&#xff0c;保障 Windows 系统安全至关重要。Ansible 作为一款强大的自动化运维工具&#xff0c;可通过自动化脚本实现 Windows 安全基线检查和加固&#xff0c;大幅提升运维效率并…

深度解析 MyBatis`@TableField(typeHandler = JacksonTypeHandler.class)`:优雅处理复杂数据存储

一、引言&#xff1a;当Java对象遇见数据库 在现代应用开发中&#xff0c;我们经常面临一个关键问题&#xff1a;如何将复杂的Java对象&#xff08;如Map、List或自定义POJO&#xff09;优雅地存储到关系型数据库中&#xff1f;传统解决方案需要开发者手动进行序列化和反序列化…

【无标题】四色定理研究团队的构建与实施路径——跨学科建模、编程与理论拓展的全流程方案

### **四色定理研究团队的构建与实施路径** **——跨学科建模、编程与理论拓展的全流程方案** --- #### **一、团队构建与核心分工** ##### **1.1 核心角色与技能需求** | **角色** | **职责** | **技能要求** …

SQLMesh增量模型实战指南:时间范围分区

引言 在数据工程领域&#xff0c;处理大规模数据集和高频率数据更新是一项挑战。SQLMesh作为一款强大的数据编排工具&#xff0c;提供了增量模型功能&#xff0c;帮助数据工程师高效地管理和更新数据。本文将详细介绍如何使用SQLMesh创建和管理基于时间范围的增量模型&#xf…

TCP vs UDP:核心区别、握手过程与应用场景(附对比图)

&#x1f310; 引言 在网络通信中&#xff0c;TCP&#xff08;传输控制协议&#xff09;和UDP&#xff08;用户数据报协议&#xff09;是两大核心传输层协议。它们各有优劣&#xff0c;适用于不同场景。本文将用图文对比实战示例&#xff0c;帮你彻底理解两者的区别&#xff0…

STM32F103C8T6信息

STM32F103C8T6 完整参数列表 一、核心参数 内核架构‌ ARM Cortex-M3 32位RISC处理器 最大主频&#xff1a;72 MHz&#xff08;基于APB总线时钟&#xff09; 运算性能&#xff1a;1.25 DMIPS/MHz&#xff08;Dhrystone 2.1基准&#xff09; 总线与存储‌ 总线宽度&#xff…

WPF-遵循MVVM框架创建图表的显示【保姆级】

文章速览 1、技术栈实现步骤1、创建WPF工程项目2、引入框架 Caliburn.Micro、数据可视化库ScottPlot.WPF3、创建文件夹&#xff0c;并创建相应的View & ViewModel4、创建启动类5、将启动类设置为启动项6、编写View7、编写VM8、将VM和View中的图表进行绑定9、备注 示例效果 …

kafka理论学习汇总

基础知识 基本简介 Kafka 是一个分布式流式处理平台&#xff0c;是一种分布式的&#xff0c;基于发布/订阅的消息系统。 Kafka特点&#xff1a; 1. 同时为发布和订阅提供高吞吐量 Kafka 的设计目标是以时间复杂度为 O(1) 的方式提供消息持久化能力&#xff0c;即使对 TB 级以…

【亚马逊云】AWS Wavelength 从理论讲解到实验演练

&#x1faaa; 本文作者&#xff1a;许业宝 ✍️ 作者信息&#xff1a; &#x1f31e; VSTECS 云解决方案架构师 &#xff5c; AWS Ambassador &#xff5c; &#x1faaa; AWS Community Builder | 亚马逊云科技技能云博主 ⭐ 已获六项 AWS 认证 | CKA、CKS认证 &#xff5c; …

ORACLE DATAGUARD遇到GAP增量恢复方式修复RAC环境备机的实践

ORACLE DATAGUARD技术是一个常用的数据保护机制&#xff0c;在DATAGUARD运行过程中&#xff0c;遇到异常导致备机不同步&#xff0c;而主库的归档日志也被清理&#xff0c;此时出现GAP&#xff0c;无法同步&#xff1b;就需要人工处理&#xff1b;对于小型数据库重新全量同步数…

Java24 抗量子加密:后量子时代的安全基石

一、量子计算威胁与 Java 的应对 随着量子计算机的快速发展&#xff0c;传统加密算法面临前所未有的挑战。Shor 算法可在多项式时间内破解 RSA、ECC 等公钥加密体系&#xff0c;而 Grover 算法能将对称加密的暴力破解效率提升至平方根级别。据 NIST 预测&#xff0c;具备实用价…

day005

文章目录 1. Linux系统核心文件1.1 查看系统版本信息1.1.1 /etc/os-release1.1.2 hostnamectl 1.2 查看主机名并修改1.2.1 hostname1.2.2 cat /etc/hostname1.2.3 hostnamectl 1.3 查看Linux内核版本1.3.1 uname -r1.3.2 hostnamectl 1.4 查看网卡信息并修改1.4.1 nmtui 网络管…