java自定义异常需继承runtimeexception并由@controlleradvice中@exceptionhandler(businessexception.class)显式捕获,确保异常从controller抛出且未被吞没,推荐使用@restcontrolleradvice简化json响应。

Java 中自定义异常要在全局异常中统一拦截,核心是让自定义异常能被 @ControllerAdvice 类里的 @ExceptionHandler 方法精准识别并处理。关键不在于“怎么抛”,而在于“怎么设计+怎么注册+怎么匹配”。
自定义异常类要继承 RuntimeException(推荐)
业务异常通常属于非检查异常,不强制上层 try-catch,也更符合 REST 接口语义。继承 RuntimeException 是主流做法:
- 避免在 Service 或 Controller 层频繁声明
throws - 确保异常能自然“穿透”到 Controller 层,最终被
@ControllerAdvice捕获 - 示例写法:
public class BusinessException extends RuntimeException {<br> private final String code;<br><br> public BusinessException(String code, String message) {<br> super(message);<br> this.code = code;<br> }<br><br> public String getCode() { return code; }<br>}
@ExceptionHandler 必须显式声明捕获该类型
全局处理器不会自动识别所有自定义异常,必须在方法参数中明确写出异常类型:
- 一个
@ExceptionHandler(BusinessException.class)方法专门处理它 - 方法内可提取
code、message,封装进统一响应体(如Result.fail()或ErrorResponse) - 注意:如果同时存在多个
@ExceptionHandler,Spring 按异常类型的继承关系优先匹配子类(如OrderException extends BusinessException会优先进入@ExceptionHandler(OrderException.class))
确保异常真的抛到了 Controller 层
这是最容易被忽略的一环——全局异常处理器只对从 Controller 方法体中“抛出”的异常生效:
- ✅ 正确:Controller 中直接
throw new BusinessException("BIZ_001", "库存不足") - ❌ 无效:Service 层抛了
BusinessException,但 Controller 用try-catch吞掉并返回 null 或空对象 → 异常没上浮,@ControllerAdvice完全收不到 - ⚠️ 注意:Filter、Interceptor、@Scheduled 任务中的异常也不走此链路,需另配方案(如
Thread.setDefaultUncaughtExceptionHandler)
配合 @RestControllerAdvice 提升开发效率
比起 @ControllerAdvice + @ResponseBody 组合,直接用 @RestControllerAdvice 更简洁:
- 自动为所有处理方法添加
@ResponseBody,返回值直接序列化为 JSON - 无需每个方法都加
@ResponseBody,减少样板代码 - 类本身仍会被 Spring 扫描为 Bean,只要放在组件扫描路径下即可
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











