java自定义异常在spring全局异常处理器中捕获需两步:一是继承runtimeexception规范定义(含code和message构造方法),二是用@controlleradvice与@exceptionhandler统一处理;抛出时须直接throw,避免包装,且确保类被组件扫描到。

Java 自定义异常在 Spring 全局异常处理器中捕获,核心在于两步:一是正确定义自定义异常类(通常继承 RuntimeException 或 Exception),二是用 @ControllerAdvice + @ExceptionHandler 统一处理它。
自定义异常类要规范
推荐继承 RuntimeException(非检查异常),避免强制 try-catch,更符合 REST API 的设计习惯:
public class BusinessException extends RuntimeException {
private int code;
public BusinessException(int code, String message) {
super(message);
this.code = code;
}
public int getCode() {
return code;
}
}
如果需要区分业务错误和系统错误,可再抽象出基类或加枚举状态码,但不要过度设计。关键点:
- 必须提供带
message的构造方法,方便日志和响应体填充 - 建议携带
code字段用于前端识别错误类型(如 4001、5002) - 不需要实现
Serializable(除非要远程传输,Spring Web 场景一般不用)
@ControllerAdvice 必须能扫描到
全局异常处理器需被 Spring 容器管理,且类路径在组件扫描范围内:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
@ResponseBody
public ResponseEntity<apiresponse> handleBusinessException(BusinessException e) {
return ResponseEntity.status(400)
.body(ApiResponse.fail(e.getCode(), e.getMessage()));
}
}</apiresponse>
注意几个细节:
-
@ControllerAdvice默认拦截所有@Controller和@RestController,无需额外配置 - 若只针对某包下的控制器,可用
@ControllerAdvice("com.example.controller") - 确保该类不在
@ComponentScan排除路径中;若使用 Spring Boot,放在主启动类同包或子包下即可自动注册
抛出自定义异常要直接、明确
在 Service 或 Controller 中,不要包装再抛,否则 @ExceptionHandler 可能匹配不到:
- ✅ 正确:
throw new BusinessException(4001, "用户名已存在"); - ❌ 错误:
throw new RuntimeException(new BusinessException(...)); - ⚠️ 注意:若用了 AOP(如事务切面),确保异常未被吞掉;
@Transactional默认只对RuntimeException回滚,所以继承RuntimeException更稳妥
补充:统一响应结构建议配套使用
返回给前端的 JSON 建议封装为标准格式,比如:
public class ApiResponse<t> {
private int code;
private String message;
private T data;
public static <t> ApiResponse<t> fail(int code, String message) {
return new ApiResponse(code, message, null);
}
// 构造方法、getter 省略
}</t></t></t>
这样前端可以统一解析 code 和 message,避免每个接口自己拼 JSON。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











