推荐使用@controlleradvice+@exceptionhandler实现全局异常处理,统一返回含code、message、timestamp的result json结构,并可通过@responsebodyadvice自动包装正常响应为result。

在 Spring Boot 项目中,推荐使用 @ControllerAdvice + @ExceptionHandler 实现全局异常处理,并统一返回标准 JSON 错误结构(如包含 code、message、timestamp 等字段),避免每个 Controller 重复写错误响应逻辑。
定义统一错误响应体
先创建一个通用的 JSON 响应封装类,用于所有接口(包括成功和失败):
public class Result<t> {
private int code;
private String message;
private T data;
private long timestamp = System.currentTimeMillis();
// 构造方法、getter/setter 略
public static <t> Result<t> fail(int code, String message) {
Result<t> r = new Result();
r.code = code;
r.message = message;
return r;
}
public static <t> Result<t> success(T data) {
Result<t> r = new Result();
r.code = 200;
r.message = "success";
r.data = data;
return r;
}
}
</t></t></t></t></t></t></t>
编写全局异常处理器
用 @ControllerAdvice 拦截所有控制器抛出的异常,按异常类型返回对应 Result:
@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()
.stream()
.map(error -> error.getField() + ": " + error.getDefaultMessage())
.collect(Collectors.joining("; "));
return Result.fail(400, "参数校验失败: " + msg);
}
// 处理空指针、运行时异常等未预期错误(生产环境建议记录日志并返回通用错误码)
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public Result<void> handleRuntimeException(RuntimeException e) {
// 生产中建议打 ERROR 日志,不暴露堆栈给前端
log.error("系统运行时异常", e);
return Result.fail(500, "服务内部错误");
}
}
</void></void></void>
确保返回 JSON 且状态码正确
Spring Boot 默认会将 @ResponseBody 方法的返回对象序列化为 JSON。还需注意两点:
- 在
@ExceptionHandler方法上加@ResponseStatus(HttpStatus.XXX)可设置 HTTP 状态码(如@ResponseStatus(HttpStatus.BAD_REQUEST)) - 若希望所有错误响应都带状态码,也可在
Result.fail()中统一设 status,再配合ResponseEntity<result></result>返回(更灵活) - 确认项目已引入
spring-boot-starter-web(含 Jackson 自动配置)
可选:统一拦截所有接口,避免手动返回 Result
如果希望所有正常接口也自动包装成 Result,可用 @ResponseBodyAdvice 做响应增强:
@ControllerAdvice
public class ResponseWrapper implements ResponseBodyAdvice<object> {
@Override
public boolean supports(MethodParameter returnType, Class extends HttpMessageConverter>> converterType) {
return true; // 对所有 @ResponseBody 方法生效
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType,
MediaType selectedContentType, Class extends HttpMessageConverter>> selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response) {
if (body instanceof Result) {
return body; // 已是 Result,不再包装
}
return Result.success(body);
}
}
</object>
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











