专家级Spring Boot全局异常处理需分层拦截(4xx/业务/5xx)、精准响应(多格式、requestId、多语言)、安全可控(生产隐藏敏感信息)、可观测强(结构化日志、监控打点、熔断降级),并规避异步异常遗漏、Security异常绕过等陷阱。

掌握 Spring Boot 全局异常处理的专家级技巧,关键不在“堆功能”,而在于**分层拦截、精准响应、安全可控、可观测强**。它不是写一个 @RestControllerAdvice 就算完成,而是构建一套有逻辑、可演进、贴合业务的异常治理体系。
按异常来源和语义分层拦截
不要把所有异常都交给一个 @ExceptionHandler(Exception.class) 兜底。专家做法是建立清晰的异常分类链:
-
客户端错误(4xx):如参数校验失败(
MethodArgumentNotValidException)、路径不匹配(NoHandlerFoundException)、权限不足(AccessDeniedException)——统一返回 400/401/403/404,带业务可读提示,不记 ERROR 级日志 -
业务异常(自定义):如
InsufficientBalanceException、OrderAlreadyPaidException——用@ResponseStatus(HttpStatus.CONFLICT)或手动设状态码,返回明确 code + message,日志级别为 WARN -
系统异常(5xx):如
SQLException、RedisConnectionFailureException、未捕获的RuntimeException——一律返回 500,message 固定为“系统繁忙,请稍后再试”,绝不暴露堆栈或数据库表名等敏感信息,日志级别为 ERROR 并记录完整异常
让异常响应真正“懂业务”
专家级响应不是只返回 JSON,而是具备上下文感知能力:
- 自动识别请求头
Accept: application/json或application/xml,动态适配序列化格式(配合ResponseEntity+HttpMessageConverter) - 在错误响应体中嵌入
requestId(可通过TraceFilter或 MDC 注入),方便日志全链路追踪 - 对不同环境差异化处理:开发环境可加
"debugInfo": "xxx"字段(仅限 local/dev),生产环境彻底移除 - 结合
MessageSource实现多语言错误消息,比如messageSource.getMessage("user.not.found", null, LocaleContextHolder.getLocale())
与日志、监控、告警深度集成
异常处理不是终点,而是可观测性的起点:
- 每个
@ExceptionHandler方法内,用@Slf4j记录结构化日志:log.warn("BUSINESS_EXCEPTION user_id={}, order_id={}, msg={}", userId, orderId, e.getMessage()) - 对高频异常(如 1 分钟内同类型异常超 10 次)触发熔断或降级逻辑(可借助 Sentinel 或自定义计数器)
- 将关键业务异常(如支付失败、库存扣减失败)打点到 Prometheus,指标名如
app_business_exception_total{type="payment_failed"} - 通过 AOP 在异常处理器执行前后埋点,统计平均处理耗时、各异常类型占比,用于稳定性分析
避免常见高阶陷阱
这些细节决定是否真能“扛住生产”:
-
不要在异常处理器里抛新异常:否则会进入默认
BasicErrorController,导致响应格式不一致 -
慎用
@ControllerAdvice(basePackages = "..."):若包路径配置错误,会导致部分 Controller 异常未被拦截;推荐用@RestControllerAdvice默认全局生效,再用@Order控制多个 Advice 执行顺序 -
Spring Security 异常需单独处理:如认证失败走
AuthenticationEntryPoint,授权拒绝走AccessDeniedHandler,它们不经过@ExceptionHandler -
异步方法(
@Async)抛出的异常不会被@RestControllerAdvice捕获,必须在调用方显式 try-catch 或配置AsyncUncaughtExceptionHandler


















