【Java | SpringBoot | GlobalExceptionHandler】全局异常拦截器实现思路

全局异常拦截器实现

    • [1. 对全局异常拦截器的作用的理解](#1. 对全局异常拦截器的作用的理解)
    • [2. 为什么需要全局异常拦截器](#2. 为什么需要全局异常拦截器)
    • [3. 实现的基本思路](#3. 实现的基本思路)
    • [4. 具体实现步骤](#4. 具体实现步骤)
      • [4.1 创建异常处理类](#4.1 创建异常处理类)
      • [4.2 添加异常处理方法](#4.2 添加异常处理方法)
          • [4.2.1 业务异常 类型处理](#4.2.1 业务异常 类型处理)
          • [4.2.2 参数校验异常 类型处理](#4.2.2 参数校验异常 类型处理)
          • [4.2.3 系统异常 类型处理](#4.2.3 系统异常 类型处理)
      • [4.3 实现业务异常处理](#4.3 实现业务异常处理)
    • [5. @RestControllerAdvice注解的作用](#5. @RestControllerAdvice注解的作用)
    • [6. 为什么叫"全局异常处理拦截器"](#6. 为什么叫"全局异常处理拦截器")
    • [7. 异常处理器的执行流程](#7. 异常处理器的执行流程)
    • [8. guanjian点 | key point](#8. guanjian点 | key point)
  • [2. 不同角度的思考"?](#2. 不同角度的思考“?)
    • [2.1 拦截器在框架中的角色?扮演什么角色?](#2.1 拦截器在框架中的角色?扮演什么角色?)
    • [2.2 Spring 机制怎么知道这是一个拦截器?](#2.2 Spring 机制怎么知道这是一个拦截器?)
    • [2.3 我们需要按怎样的"优先级"去拦截异常?](#2.3 我们需要按怎样的“优先级”去拦截异常?)
    • [2.4 捕获到不同异常后,分别应该做哪三件事?](#2.4 捕获到不同异常后,分别应该做哪三件事?)
      • [2.4.1 日志记录](#2.4.1 日志记录)

1. 对全局异常拦截器的作用的理解

全局异常拦截器 是一个Spring组件。

他主要是能

  1. 捕获controller层抛出来的所有异常
  2. 将捕获的所有异常转换为统一的响应格式
  3. 避免在每个controller层中重复的去编写异常处理的代码(冗余代码)
  4. 统一进行处理业务一场和系统异常

2. 为什么需要全局异常拦截器

  • 代码复用 :避免在每个Controller中编写相同的异常处理逻辑(冗余问题)
  • 统一 响应 :确保所有异常都返回相同的格式
  • 职责分离 :Controller只负责业务逻辑,不负责异常处理 (分明)
  • 安全 :避免将系统异常的详细信息暴露给前端(友好)

实现的基本思路

3. 实现的基本思路

  1. 创建异常处理类。 我们首先需要创建一个异常处理类,
  2. 添加类注解。 然后我们使用@RestControllerAdvice注解 标记为切片方法,用于捕获controller层的异常
  3. **添加异常处理方法。**对于该类的方法体,我来下一步就是定义异常处理方法:使用注解@ExceptionHandler对每个方法进行注解
  4. 异常是有多种不同类型的:业务异常、参数检验异常、系统异常
    5.添加异常处理方法注解以及标记不同异常类型。 通过@ExceptionHandler标记不同的类型
  5. 统一响应 返回。 最后我们在定义的处理异常方法中转换为统一的响应返回给前端去,此时就需要使用统一响应结果结构类中的失败方法返回Result.failure() 方法

4. 具体实现步骤

4.1 创建异常处理类

java 复制代码
@RestControllerAdvice

public class GlobalExceptionHandler {
// 异常处理方法将在这里
  
}

4.2 添加异常处理方法

例如,我们现在做的是业务异常类型的捕获处理并返回

4.2.1 业务异常 类型处理

添加异常处理方法

java 复制代码
// 处理业务异常
@ExceptionHandler(BusinessException.class)
public ResponseEntity<Result<Object>> handleBusinessException(BusinessException ex) {
    // 实现代码
}
4.2.2 参数校验异常 类型处理

添加异常处理方法

java 复制代码
// 
// 处理参数校验异常
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Result<Object>> handleValidationException(MethodArgumentNotValidException ex) {
    // 实现代码
}

yichan

4.2.3 系统异常 类型处理

添加异常处理方法

java 复制代码
// 
// 处理系统异常
@ExceptionHandler(Exception.class)
public ResponseEntity<Result<Object>> handleException(Exception ex) {
    // 实现代码
}

4.3 实现业务异常处理

5. @RestControllerAdvice注解的作用

@RestControllerAdvice 是 Spring 框架提供的注解,它结合了以下功能:

  • @ControllerAdvice :定义全局控制器增强器,可以处理控制器层的异常
  • @ResponseBody :自动将返回值转换为JSON格式
  • @Component :作为Spring Bean被容器管理
    所以 @RestControllerAdvice = @ControllerAdvice + @ResponseBody + @Component

6. 为什么叫"全局异常处理拦截器"

因为它的作用机制是

  1. 全局范围 :Spring Boot启动时会自动扫描并注册这个Bean
  2. 异常拦截 :当Controller层抛出异常时,Spring会自动调用对应的异常处理方法
  3. 统一处理 :所有异常都会被这个类捕获和处理
  4. 拦截器模式 :类似于AOP的拦截器,在异常发生时介入处理

7. 异常处理器的执行流程

bash 复制代码
HTTP请求 → Controller → Service → 抛出异常
↓
Spring捕获异常 → 查找匹配的@ExceptionHandler方法
↓
执行对应的异常处理方法 → 返回统一响应

8. guanjian点 | key point

  • @RestControllerAdvice :告诉Spring这是一个全局异常处理器
    - @ExceptionHandler :指定要处理的异常类型
  • 方法签名 :返回ResponseEntity<Result > ,确保统一响应格式
    异常优先级:更具体的异常处理方法会优先匹配

    与普通Controller的区别
    普通Controller:
java 复制代码
@RestController
public class MyController {
    @GetMapping("/test")
    public String test() {
        // 业务逻辑
    }
}

全局异常处理器:
@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    public ResponseEntity<Result<Object>> handleException(Exception ex) {
        // 异常处理逻辑
    }
}

为什么它能全局生效

Spring自动扫描:启动时会注册为Bean

异常传播机制:Spring MVC框架会自动将Controller抛出的异常交给异常处理器

注解驱动:通过@ExceptionHandler注解实现异常类型的匹配

这样,当任何Controller抛出异常时,都会被这个全局异常处理器捕获和处理,实现了真正的"全局"效果。

2. 不同角度的思考"?

2.1 拦截器在框架中的角色?扮演什么角色?

设想一下:当 Controller 或 Service 抛出异常时,如果不处理,Spring 会默认返回 Servlet 容器的 500/404 错误页或者 HTML

定位:GlobalExceptionHandler 是系统在 HTTP 协议出口处的最后一道防火墙 ,负责把所有抛出的 Throwable/Exception "揉平"并包装成前端契约规定的统一 Result JSON 结构。

2.2 Spring 机制怎么知道这是一个拦截器?

我们思考一下:我们需要用 Spring MVC 提供的注解 告知 Spring 容器 接管全局异常。

工具:

  • @RestControllerAdvice标注在类上 。它是 @ControllerAdvice + @ResponseBody 的组合,意味着该类捕获异常后,可以直接返回 JSON 对象。

  • @ExceptionHandler (XxxException.class):标注在具体的方法 上,告诉 Spring "如果抛出了 XxxException ,交给我这个方法来处理"。

2.3 我们需要按怎样的"优先级"去拦截异常?

Spring 匹配 @ExceptionHandler 时,遵循**"就近/精细原则"(即优先匹配更具体的子类异常,最后才匹配父类 Exception**)。

按照我们的业务设计,异常至少划分为 3 层:

bash 复制代码
[精细度 高]  1. 自定义业务异常 (BusinessException)   --> 业务规则主动拦截
    │       2. 参数校验异常 (ValidationException) --> 客户端传参错误
[精细度 低]  3. 未预期系统异常 (Exception)          --> 兜底拦截(空指针、数据库故障等)

2.4 捕获到不同异常后,分别应该做哪三件事?

对于被拦截的每一个异常 ,处理函数内部 固定执行标准三部曲

  1. 日志记录(Log):
  • 业务 异常/参数 校验:打 log.warn (不需要打堆栈 ,属于正常业务拦停)。

  • 未预期系统异常 :打 log.error ("...", ex)(必须打印完整堆栈 ,用于排查线上传奇 Bug)。

  1. HTTP 状态码映射(HTTP Status):

比如

STORE_NOT_FOUND 映射为 HTTP 404

参数错误映射为 HTTP 400。

系统错误映射为 HTTP 500。

  1. 返回统一响应体(Response Body):

统一调用 Result.failure(...) 组装结构。

失败响应的 data 统一置为 null。

绝对不能把未预期异常(如 SQL 语法错误、NullPointer)的原始 ex.getMessage() 吐给前端,防止泄露数据表结构或安全隐患斜体样式

2.4.1 日志记录

相关推荐
浮江雾7 小时前
Flutter第十节-----Flutter布局与组件全解析
android·开发语言·前端·学习·flutter·入门
爱喝水的鱼丶7 小时前
SAP-ABAP:ALV跨版本兼容指南——适配ECC与S4 HANA系统的ALV开发注意事项
开发语言·性能优化·sap·abap·经验交流
风起洛阳@不良使7 小时前
spring中xml和注解开发的对比
xml·java·spring
布朗克1687 小时前
Go 入门到精通-27-泛型编程
开发语言·golang·xcode·泛型编程
Tenifs7 小时前
关闭 IDEA 的英文单词拼写检查
java·intellij-idea
cui_ruicheng7 小时前
Python从入门到实战(十五):文件操作与目录管理
开发语言·python
captain3767 小时前
创建多线程程序
java·java-ee
野蛮人6号7 小时前
黑马天机学堂Day01-08.搭建项目环境-本地开发部署方式——不知道nacos的密码是什么
java·spring cloud·黑马程序员·天机学堂·黑马天机学堂
Roy_Sashulin7 小时前
灵杉Java编程平台第一章:安装
java·开发语言
名字还没想好☜7 小时前
Go 用 errgroup 管理并发子任务:错误收敛、取消传播与限流
开发语言·后端·golang·go·并发