Spring全局异常处理最佳实践

全局异常处理器详解

什么是全局异常处理器?

全局异常处理器是Spring框架提供的统一异常处理机制,用于集中处理应用程序中所有控制器(Controller)层抛出的异常。它的核心价值在于:

  1. 统一异常处理:避免在每个Controller方法中重复编写try-catch
  2. 标准化错误响应:确保所有异常返回一致的错误格式
  3. 解耦业务逻辑:将错误处理与业务代码分离
  4. 提高可维护性:所有异常处理逻辑集中管理
  5. 增强安全性:防止敏感异常信息泄露给客户端

核心实现方式

1. 使用 @ControllerAdvice + @ExceptionHandler(推荐)

@RestControllerAdvice // 组合了@ControllerAdvice和@ResponseBody
public class GlobalExceptionHandler {// 处理自定义业务异常@ExceptionHandler(BusinessException.class)public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex) {ErrorResponse error = new ErrorResponse(ex.getErrorCode(),ex.getMessage(),System.currentTimeMillis());return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);}// 处理参数校验异常@ExceptionHandler(MethodArgumentNotValidException.class)public ResponseEntity<ErrorResponse> handleValidationException(MethodArgumentNotValidException ex) {List<String> errors = ex.getBindingResult().getFieldErrors().stream().map(error -> error.getField() + ": " + error.getDefaultMessage()).collect(Collectors.toList());ErrorResponse error = new ErrorResponse("VALIDATION_FAILED","参数校验失败",errors,System.currentTimeMillis());return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);}// 处理认证授权异常@ExceptionHandler(AccessDeniedException.class)public ResponseEntity<ErrorResponse> handleAccessDeniedException(AccessDeniedException ex) {ErrorResponse error = new ErrorResponse("UNAUTHORIZED","无访问权限",System.currentTimeMillis());return new ResponseEntity<>(error, HttpStatus.FORBIDDEN);}// 处理所有未捕获的异常@ExceptionHandler(Exception.class)public ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex) {// 生产环境应隐藏详细错误信息String message = "生产环境".equals(env) ? "服务器内部错误" : ex.getMessage();ErrorResponse error = new ErrorResponse("INTERNAL_SERVER_ERROR",message,System.currentTimeMillis());log.error("未处理异常: ", ex);return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);}
}

2. 错误响应体结构(标准化)

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ErrorResponse {private String code;      // 错误码private String message;   // 用户友好消息private Object details;   // 错误详情(可选)private long timestamp;   // 时间戳// 用于校验错误的构造器public ErrorResponse(String code, String message, Object details, long timestamp) {this.code = code;this.message = message;this.details = details;this.timestamp = timestamp;}
}

企业级最佳实践

1. 异常分类处理策略

异常类型HTTP状态码处理方式
业务逻辑异常400返回具体错误码和用户友好消息
参数校验异常400返回具体字段错误信息
认证失败异常401返回认证失败提示
权限不足异常403返回权限不足提示
资源不存在异常404返回资源不存在提示
系统内部异常500返回通用错误(生产环境屏蔽细节)
服务不可用异常503返回服务维护提示

2. 自定义业务异常体系

// 基础业务异常
public 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);}
}public class InsufficientBalanceException extends BusinessException {public InsufficientBalanceException(BigDecimal balance) {super("INSUFFICIENT_BALANCE", "余额不足,当前余额: " + balance);}
}

3. 自动处理参数校验

结合 @Valid 注解自动捕获校验异常:

@PostMapping("/users")
public UserDTO createUser(@Valid @RequestBody CreateUserRequest request) {// 业务逻辑
}// 在全局异常处理器中
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidationException(MethodArgumentNotValidException ex) {// 提取所有字段错误Map<String, String> errors = ex.getBindingResult().getFieldErrors().stream().collect(Collectors.toMap(FieldError::getField,fieldError -> fieldError.getDefaultMessage() != null ? fieldError.getDefaultMessage() : ""));return ResponseEntity.badRequest().body(new ErrorResponse("VALIDATION_ERROR", "参数校验失败", errors));
}

4. 生产环境安全处理

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex) {// 区分开发和生产环境String errorMessage = "系统错误";// 开发环境显示详细错误if ("dev".equals(environment.getProperty("spring.profiles.active"))) {errorMessage = ex.getMessage();}// 记录完整错误日志log.error("未处理异常: ", ex);return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ErrorResponse("SERVER_ERROR", errorMessage));
}

高级功能扩展

1. 异常国际化支持

@ExceptionHandler(BusinessException.class)
public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex, HttpServletRequest request) {// 从请求头获取语言String language = request.getHeader("Accept-Language");Locale locale = StringUtils.hasText(language) ? Locale.forLanguageTag(language) : Locale.getDefault();// 使用MessageSource获取本地化消息String localizedMessage = messageSource.getMessage(ex.getErrorCode(), new Object[]{}, ex.getMessage(), // 默认消息locale);return ResponseEntity.badRequest().body(new ErrorResponse(ex.getErrorCode(), localizedMessage));
}

2. 异常监控集成

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex) {// 发送异常到监控系统metricsService.recordException(ex);// 发送告警通知if (ex instanceof CriticalException) {alertService.sendCriticalAlert(ex);}// ... 其他处理
}

3. 自定义异常处理器顺序

@Order(Ordered.HIGHEST_PRECEDENCE) // 最高优先级
@RestControllerAdvice
public class SecurityExceptionHandler {@ExceptionHandler(AuthenticationException.class)public ResponseEntity<ErrorResponse> handleAuthException(AuthenticationException ex) {// 特殊处理认证异常}
}@Order(Ordered.LOWEST_PRECEDENCE) // 最低优先级
@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)public ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex) {// 兜底处理}
}

使用场景示例

Controller中的使用

@RestController
@RequestMapping("/api/orders")
public class OrderController {@PostMappingpublic ResponseEntity<OrderDTO> createOrder(@Valid @RequestBody CreateOrderRequest request) {// 业务代码无需处理异常OrderDTO order = orderService.createOrder(request);return ResponseEntity.ok(order);}@GetMapping("/{id}")public ResponseEntity<OrderDTO> getOrder(@PathVariable Long id) {// 直接抛出业务异常OrderDTO order = orderService.getOrder(id).orElseThrow(() -> new OrderNotFoundException(id));return ResponseEntity.ok(order);}
}

最佳实践总结

  1. 分层处理

    • 业务层抛出有含义的异常
    • 控制器层不处理异常
    • 全局处理器统一转换异常为响应
  2. 标准化响应

    • 统一错误响应格式
    • 包含错误码、消息和时间戳
    • 必要时添加错误详情
  3. 异常分类

    • 为不同类型异常创建处理器
    • 使用HTTP状态码合理映射业务异常
  4. 安全考虑

    • 生产环境屏蔽敏感异常信息
    • 开发环境显示详细错误
  5. 监控集成

    • 记录异常日志
    • 集成监控告警系统
  6. 可扩展性

    • 使用自定义异常体系
    • 支持异常国际化

全局异常处理器是构建健壮REST API的关键组件,它能显著提高代码质量、增强系统稳定性,并为客户端提供一致的错误处理体验。

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

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

相关文章

STL学习(十一、常用的算数算法和集合算法)

目录 一、常用的算数算法 1.accmulate 2.fill 二、常用的集合算法 1.set_intersection 2.set_union 3.set_difference 一、常用的算数算法 包含头文件为<numeric> 1.accmulate 函数原型 accmulate(iterator beg, iterator end, value) // 计算元素累计和 // …

DeepSort 算法分析详解

DeepSort 算法分析详解 DeepSort 简介 DeepSort (Deep Learning Sort) 是一种基于深度学习的多目标跟踪算法&#xff0c;由 Wojke 等人于 2017 年提出。它是对传统 Sort (Simple Online and Realtime Tracking) 算法的改进&#xff0c;通过引入深度特征提取网络来增强目标关联的…

基于深度学习的医学图像分析:使用Capsule Networks实现医学图像分类

前言 医学图像分析是计算机视觉领域中的一个重要应用&#xff0c;特别是在医学图像分类任务中&#xff0c;深度学习技术已经取得了显著的进展。医学图像分类是指将医学图像分配到预定义的类别中&#xff0c;这对于疾病的早期诊断和治疗具有重要意义。近年来&#xff0c;Capsule…

G9打卡——ACGAN

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 1.导入库及参数 import argparse import os import numpy as npimport torchvision.transforms as transforms from torchvision.utils import save_imagefrom…

应用war/jar包是用TongWeb企业版,还是嵌入版?

在判断应用应该采用TongWeb哪个版本时&#xff0c;存在一种错误的观点&#xff1a;如果应用包是jar包&#xff0c;则需要采用TongWeb嵌入版&#xff1b;如果应用包是war包&#xff0c;则需要采用TongWeb企业版。 正确的判断方法&#xff1a;1. 首先应用为jar包&#xff0c;且符…

Linux ARM 平台 C 语言操作 Excel 文件的常用库与工具汇总(支持 xls 和 xlsx)

在 Linux 或嵌入式 ARM 平台开发中&#xff0c;使用 C 语言操作 Excel 文件是一项常见需求&#xff0c;特别是在工业设备数据采集、日志导出、报表生成等场景。Excel 文件格式复杂&#xff0c;手工解析成本高&#xff0c;因此使用现成的库可以极大简化开发工作。 本文整理了若…

Apache Ignite 集群标识(Cluster ID)和集群标签(Cluster Tag)

这是一个关于 Apache Ignite 集群标识&#xff08;Cluster ID&#xff09;和集群标签&#xff08;Cluster Tag&#xff09; 的重要配置概念。我们来一步步深入理解这段文档的含义&#xff0c;并结合实际场景说明其用途。&#x1f9e9; 一、核心概念&#xff1a;Cluster ID 与 C…

基于 Hadoop 生态圈的数据仓库实践 —— OLAP 与数据可视化(三)

目录 三、Impala OLAP 实例 1. 建立 olap 库、表、视图 2. 初始装载数据 3. 修改销售订单定期装载脚本 4. 定义 OLAP 需求 5. 执行 OLAP 查询 三、Impala OLAP 实例 本节使用前面销售订单的例子说明如何使用 Impala 做 OLAP 类型的查询&#xff0c;以及实际遇到的问题及解…

如何不让android studio自动换行

一、关闭逗号后自动换行设置 打开设置界面 进入 File → Settings &#xff08;Windows/Linux&#xff09;或 Preferences &#xff08;macOS&#xff09;。 导航至 Editor → Code Style → 选择语言&#xff08;如 Java 或 Kotlin &#xff09;。 二、修改换行规则…

Jenkinsfile 报错

Started by user 六件套Obtained Jenkinsfile from git https://gitee.com/duoshuijiao/vitepress-jenkins-cicd-demoorg.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:WorkflowScript: 28: Expected a step line 28, column 66.fingerprint:…

工业一体机全封闭抗干扰赋能自动化产线高效作业

在自动化产线智能设备等工业场景中&#xff0c;工业一体机的应用面临多重挑战&#xff1a;高温、粉尘、电磁干扰等恶劣环境易导致设备误操作&#xff0c;传统工控机平均无故障时间不足4000小时&#xff1b;封闭车间散热效率低下&#xff0c;风扇散热失效风险增加&#xff0c;产…

鸿蒙NEXT开发笔记(二十八)仿抖音快手App的把位图数据转存为图片

上一节我们利用Scroller实现了列表项的自动滚动功能&#xff0c;对于图像列表来说&#xff0c;被选做封面的图像需要保存为图片文件&#xff0c;以便向服务器上传封面图片。 由于avImageGenerator从视频提取的图像帧数据为image.PixelMap&#xff08;位图格式&#xff09;&…

四、搭建springCloudAlibaba2021.1版本分布式微服务-加入openFeign远程调用和sentinel流量控制

OpenFeign远程调用 1、OpenFeign OpenFeign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用OpenFeign&#xff0c;可以做到使用HTTP请求访问远程服务&#xff0c;就像调用本地方法一样的&#xff0c;开发者完全感知不到这是在调用远程方法&#xff0c;更感知不到在访问…

网络安全威胁——APT攻击_apt攻击预测案例

APT攻击 1. 基本概念2. APT的攻击阶段3. APT的典型案例参考 1. 基本概念 高级持续性威胁&#xff08;APT&#xff0c;Advanced Persistent Threat&#xff09;&#xff0c;又叫高级长期威胁&#xff0c;是一种复杂的、持续的网络攻击&#xff0c;包含高级、长期、威胁三个要…

顺时针旋转N * N 的矩阵

顺时针旋转题目描述数据范围实现逻辑代码实现题目描述 有一个NxN整数矩阵&#xff0c;请编写一个算法&#xff0c;将矩阵顺时针旋转90度。给定一个NxN的矩阵&#xff0c;和矩阵的阶数N,请返回旋转后的NxN矩阵。数据范围 0<n<300&#xff0c;矩阵中的值满足 0≤val≤100…

原生C++实现信号与槽机制:原理详解

信号与槽机制是一种广泛应用于事件驱动系统和GUI框架&#xff08;如Qt&#xff09;的设计模式。它允许组件之间通过订阅-发布模式进行通信&#xff0c;从而实现松耦合的设计。本文将详细讲解如何在原生C中从零开始实现信号与槽机制&#xff0c;并深入探讨其工作原理。一、信号与…

【人工智能】OpenAI的AI代理革命:通向超拟人交互的未来之路

人工智能代理(AI Agent)正引领一场深刻的技术变革,其核心在于赋予AI系统感知、规划、行动和学习的能力,以自主完成复杂任务。OpenAI作为这一领域的先驱,通过其大型语言模型(LLMs)如GPT系列,极大地推动了AI代理的发展,使其在自然语言理解、生成和工具使用方面达到了前所…

Ubuntu虚拟机介绍、命令、安装软件指令(一)

Ubuntu介绍 Ubuntu 是一个基于 Debian 的开源 Linux 操作系统&#xff0c;由 Canonical 公司赞助开发。它是目前全球最流行的 Linux 发行版之一&#xff0c;以其用户友好性、稳定性和强大的社区支持著称。 核心特性 1.免费开源 完全免费使用和分发&#xff0c;遵循 GNU GPL…

企业微信服务商创建第三方应用配置数据回调url和指令回调url的java代码实现

关键区别说明&#xff08;指令回调 vs 数据回调&#xff09;特性指令回调数据回调触发场景授权/取消授权等管理事件通讯录变更、应用菜单点击等业务事件关键字段InfoTypeEvent ChangeType典型事件suite_auth, cancel_authchange_contact, suite_ticket响应要求必须返回加密的&…

LazyLLM教程 | 第2讲:10分钟上手一个最小可用RAG系统

贴心小梗概本文将介绍使用LazyLLM搭建最基础的RAG的流程。首先介绍使用LazyLLM搭建RAG系统的必要环境配置&#xff0c;然后简单回顾RAG的基本流程&#xff0c;接下来分别介绍RAG中文档加载、检索组件、生成组件三个关键部分的参数和基本使用方法&#xff0c;最后利用LazyLLM实现…