全局异常未生效主因是异常未传到处理器:被提前捕获、过滤器/拦截器吞掉、@async或线程池静默处理、@controlleradvice扫描路径不符、方法误用static、自定义异常未继承runtimeexception等。

全局异常未生效,通常不是“没写对”,而是“没走到”——异常在到达全局处理器前就被拦截、吞掉或绕过了。排查要从异常传播路径和Spring的处理机制两头入手。
检查异常是否被提前捕获或静默处理
很多异常根本没机会传到@ControllerAdvice,因为它们在业务层、框架层甚至JVM层就被截断了:
- Service 或 DAO 层用了 try-catch 吞掉了异常,且没有 re-throw 或抛出新异常
- @Async 方法抛异常后,若没调用 Future.get(),异常会留在 Future 内部,永远不会暴露
- 线程池中子线程抛异常,默认静默终止;未通过 ThreadFactory 统一设置 UncaughtExceptionHandler
- 过滤器(Filter)或拦截器(Interceptor)中发生异常,且未显式 throw,会导致请求中断但不触发全局异常处理器
确认 @ControllerAdvice 的作用范围是否匹配
@ControllerAdvice 默认只对 @Controller 和 @RestController 生效,但实际行为受其配置约束:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 检查是否加了 basePackages 限制,比如 @ControllerAdvice(basePackages = "com.example.api"),而异常发生在 com.example.service 包下
- 确认是否指定了 annotations,例如 @ControllerAdvice(annotations = RestController.class),但目标 Controller 是普通 @Controller
- Spring Boot 2.6+ 默认禁用 @ControllerAdvice 对非 Web MVC 场景的支持,若用 WebFlux 需改用 @ControllerAdvice + @RestControllerAdvice 不适用,应换为 ExceptionHandlerFunction
验证异常类型是否被正确匹配
@ExceptionHandler 按异常类型继承关系匹配,但容易因“太宽泛”或“太狭窄”失效:
- 写了 @ExceptionHandler(Exception.class) 却发现没进,可能是异常被更具体的处理器先捕获(如 Spring 自带的 ResponseStatusExceptionResolver 处理了 4xx/5xx 异常)
- 自定义异常未继承 RuntimeException,而方法上又没声明 throws,部分场景下可能被包装成 UndeclaredThrowableException
- 参数校验异常(如 MethodArgumentNotValidException)需显式声明 @ExceptionHandler,不能靠 Exception.class 通吃,因为它是 RuntimeException 的子类但有特殊处理链
观察 DispatcherServlet 异常分发是否完成
全局异常处理器本质是 HandlerExceptionResolver 的实现,依赖 DispatcherServlet 的异常分发流程:
- 在 application.properties 中临时开启 debug 日志:logging.level.org.springframework.web.servlet.DispatcherServlet=DEBUG,看异常是否进入 dispatch 流程
- 检查是否有多个 @ControllerAdvice 类,且存在优先级冲突(可通过 @Order 注解控制顺序,数值越小优先级越高)
- 确保全局处理器类被 Spring 容器扫描到:类不在@ComponentScan 范围内、缺少 @Component/@Configuration 等注解、或被条件化(@ConditionalOnMissingBean)排除










