统一异常处理的核心是用@controlleradvice+@exceptionhandler全局捕获未处理异常并转为标准json响应,配合@responsestatus设置http状态码,确保前后端协同识别错误类型。

在 Java Web 项目中(尤其是 Spring Boot),统一异常处理的核心是捕获所有未处理的异常,并将其转换为格式一致的 JSON 响应,比如 {"code": 500, "message": "服务器内部错误", "data": null}。关键不在于“每个方法都 try-catch”,而是在全局层面拦截、转换、标准化输出。
定义统一响应结构
先创建一个通用的响应体类,确保所有接口(无论成功或失败)都返回同一类型:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
public class Result<t> {
private int code;
private String message;
private T data;
public static <t> Result<t> success(T data) {
Result<t> r = new Result();
r.code = 200;
r.message = "success";
r.data = data;
return r;
}
public static <t> Result<t> fail(int code, String message) {
Result<t> r = new Result<t>();
r.code = code;
r.message = message;
r.data = null;
return r;
}
// getter/setter 省略
}
</t></t></t></t></t></t></t></t>
使用 @ControllerAdvice + @ExceptionHandler 全局捕获
新建一个配置类,用 @ControllerAdvice 标记,集中处理 Controller 层抛出的异常:
@ControllerAdvice
public class GlobalExceptionHandler {
// 捕获业务异常(如自定义的 BusinessException)
@ExceptionHandler(BusinessException.class)
@ResponseBody
public Result<void> handleBusinessException(BusinessException e) {
return Result.fail(e.getCode(), e.getMessage());
}
// 捕获参数校验异常(@Valid 失败时)
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public Result<void> handleValidationException(MethodArgumentNotValidException e) {
String msg = e.getBindingResult().getFieldErrors().get(0).getDefaultMessage();
return Result.fail(400, "参数错误: " + msg);
}
// 捕获所有其他未明确处理的异常(兜底)
@ExceptionHandler(Exception.class)
@ResponseBody
public Result<void> handleException(Exception e) {
e.printStackTrace(); // 生产环境建议用日志框架记录
return Result.fail(500, "系统繁忙,请稍后再试");
}
}
</void></void></void>
- 注意:方法必须加
@ResponseBody(或类上加@RestControllerAdvice),否则不会序列化为 JSON - 异常处理顺序按方法声明顺序匹配,更具体的异常(如 BusinessException)应放在更通用的(如 Exception)之前
- 不要在 handler 里 throw 新异常,否则会再次触发处理逻辑,可能造成循环
配合状态码(HTTP Status Code)增强语义
仅改 JSON 内容不够,前端常依赖 HTTP 状态码做统一判断。可在 @ExceptionHandler 方法上加 @ResponseStatus:
@ExceptionHandler(BusinessException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public Result<void> handleBusinessException(BusinessException e) {
return Result.fail(400, e.getMessage());
}
</void>
-
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)对应 500 -
@ResponseStatus(HttpStatus.NOT_FOUND)对应 404(可配合NoHandlerFoundException捕获) - 确保前端能同时读取 HTTP 状态码和响应体中的
code字段,二者可分工:状态码表网络/框架层问题,body.code 表业务层错误码
避免常见坑
-
过滤器或拦截器中抛的异常不会被 @ControllerAdvice 捕获 —— 需单独在 filter 中 try-catch,或改用 Spring 的
OncePerRequestFilter+errorPage配置 -
异步方法(
@Async)中的异常不会到达 ControllerAdvice —— 要么不用 @Async,要么手动捕获并发布事件,或改用CompletableFuture显式处理 -
JSON 序列化异常(如对象循环引用)发生在 response 写出阶段,无法被上述 handler 拦截 —— 可通过
@ControllerAdvice实现ResponseBodyAdvice做后置处理,或配置 Jackson 全局忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










