企业级java项目需分层设计全局异常处理器:web层用@restcontrolleradvice统一拦截并返回标准响应;定义业务/系统/校验三类自定义异常;异步任务须通过threadfactory、completablefuture回调及默认异常处理器兜底;容器与jvm级依赖errorreportvalve和监控预警。

企业级 Java 项目中配置全局异常处理器,核心目标是统一响应格式、屏蔽敏感信息、区分业务异常与系统错误,并保障多场景下的异常兜底能力。不能只靠一个注解完事,得按层设计、分工明确。
Web 层统一拦截:用 @RestControllerAdvice + @ExceptionHandler
这是最常用、也最必要的第一道防线,专管 HTTP 请求生命周期内的异常。
- 定义一个类,标注 @RestControllerAdvice(比 @ControllerAdvice + @ResponseBody 更简洁,专为 REST API 设计)
- 每个 @ExceptionHandler 方法绑定具体异常类型,优先处理自定义业务异常(如
UserNotFoundException),再捕获通用异常(如IllegalArgumentException),最后用@ExceptionHandler(Exception.class)做 Web 层兜底 - 返回值建议封装为统一响应体(如
R<object></object>或Result<t></t>),附带状态码、错误码、提示消息,不直接暴露堆栈 - 配合 @Slf4j 记录完整异常日志(含堆栈),但响应体里只传用户友好的 message
定义分层的自定义异常体系
避免所有逻辑都抛 RuntimeException,而是按语义建模:
-
业务异常(如
InsufficientBalanceException):继承RuntimeException,代表可预期的业务失败,不打 ERROR 日志,响应 HTTP 400 或自定义业务码 -
系统异常(如
ServiceUnavailableException):继承RuntimeException或自定义基类,表示服务暂时不可用,响应 503 或重试提示 -
校验异常:Spring Boot 自动触发
MethodArgumentNotValidException和ConstraintViolationException,需单独捕获并提取字段级错误信息
线程池与异步任务的异常兜底
@RestControllerAdvice 对 @Async、CompletableFuture、定时任务(@Scheduled)完全无效,必须额外防护:
- 创建线程池时,使用自定义 ThreadFactory,显式设置每个线程的
UncaughtExceptionHandler,让它复用全局日志和告警逻辑 - 对
CompletableFuture,务必调用whenComplete()或exceptionally()显式处理异常,否则会静默丢失 - 在 Spring 启动类的
main()方法第一行,调用Thread.setDefaultUncaughtExceptionHandler(),覆盖主线程及默认派生线程
容器与 JVM 级最后防线
当 Web 层甚至线程池都未覆盖到的崩溃(如 Tomcat acceptor 线程异常、JVM OOM 前兆),需配合基础设施:
- Tomcat 可配置 ErrorReportValve,定制 500 页面或上报错误摘要
- JVM 级别不建议捕获
OutOfMemoryError等Error子类,应通过-XX:+HeapDumpOnOutOfMemoryError和监控系统(如 Prometheus + Grafana)提前预警 - 关键后台任务(如数据同步、消息消费)应在 catch 块内主动记录、补偿或触发人工介入流程,而非依赖全局处理器
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











