@restcontrolleradvice 拦截自定义异常的核心是“声明捕获 + 精准匹配 + 统一包装”,需定义继承 runtimeexception 的业务异常类(含 code/message 构造器和 getcode() 方法),在 @exceptionhandler(businessexception.class) 中精准捕获并封装响应,且异常必须从 controller 层向上抛出才生效。

用 @RestControllerAdvice 拦截自定义异常,核心是“声明捕获 + 精准匹配 + 统一包装”。它不依赖业务层手动 try-catch,而是由 Spring MVC 在 Controller 抛出异常后自动路由到对应处理器。
定义可识别的自定义异常类
必须让异常具备明确的业务语义和可区分特征,推荐继承 RuntimeException(避免强制 throws),并携带状态码和提示信息:
- 提供带 code 和 message 的构造方法
- 添加 getCode() 方法供处理器读取业务码
- 不需实现序列化接口,JSON 响应时只取字段值
示例:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
public class BusinessException extends RuntimeException {
private final int code;
public BusinessException(int code, String message) {
super(message);
this.code = code;
}
public int getCode() { return code; }
}
在 @RestControllerAdvice 类中用 @ExceptionHandler 捕获
处理器方法参数类型必须与自定义异常类完全一致,Spring 才能精准匹配:
- 方法签名写 @ExceptionHandler(BusinessException.class)
- 参数直接接收 BusinessException e
- 内部调用统一返回工具(如 Result.success/fail)封装响应
- 可配合 @ResponseStatus 设置 HTTP 状态码(如 400、403)
示例:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Result> handleBusinessException(BusinessException e) {
return Result.fail(e.getCode(), e.getMessage());
}
}
确保异常能真正抛到 Controller 层外
自定义异常只有从 Controller 方法体内向上抛出,才能被 @RestControllerAdvice 拦截:
- Service 层 throw BusinessException → Controller 层不 catch → 异常穿透出去
- Controller 层若自己 try-catch 了,又没 re-throw,拦截器就收不到
- 不要在 Controller 里用 return Result.fail(...) 替代 throw,那不属于“异常流”
正确触发方式:
@PostMapping("/login")
public User login(@RequestBody LoginDTO dto) {
if (!userService.validate(dto)) {
throw new BusinessException(4001, "用户名或密码错误"); // ✅ 向上抛
}
return userService.getUser(dto);
}
补充常见组合处理逻辑
一个健壮的全局处理器通常同时处理多类异常,建议按优先级顺序排列方法(越具体的异常越靠前):
- BusinessException:优先捕获,返回业务码 + 可读提示
- MethodArgumentNotValidException:处理 @Valid 校验失败,提取 BindingResult 错误信息
- Exception:兜底捕获所有未覆盖的异常,记录日志并返回通用 500
注意:多个 @ExceptionHandler 方法之间无继承关系,全靠参数类型严格匹配。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










