在Spring Boot REST API开发中,异常处理是直接影响接口易用性和项目可维护性的关键环节。如果异常处理不规范,接口可能会返回五花八门的报错格式,前端需要针对不同的错误写不同的解析逻辑,甚至还可能把服务内部的堆栈信息暴露给外部,带来安全隐患。

为什么需要规范的异常处理
默认的Spring Boot异常处理会返回包含堆栈信息的JSON或者HTML页面,这种返回格式不适合REST API场景。规范的异常处理能实现几个核心目标:
- 统一所有接口的异常返回格式,前端可以统一解析错误内容
- 隐藏服务内部实现细节,避免敏感信息泄露
- 针对不同的业务场景返回明确的错误码和提示信息
- 减少重复的异常处理代码,提升代码可维护性
第一步:定义统一的异常响应结构
首先需要定义一个通用的错误响应实体,所有异常返回都遵循这个结构,方便前端统一处理。
public class ErrorResponse {
// 错误码,用于标识不同的错误类型
private String code;
// 错误提示信息,给前端或者用户看
private String message;
// 请求路径,方便排查问题
private String path;
// 时间戳
private Long timestamp;
public ErrorResponse(String code, String message, String path) {
this.code = code;
this.message = message;
this.path = path;
this.timestamp = System.currentTimeMillis();
}
// 省略getter和setter方法
}第二步:自定义业务异常
除了系统自带的异常,我们还需要定义自己的业务异常,用来承载业务层面的错误,比如参数校验失败、资源不存在等场景。
public class BusinessException extends RuntimeException {
// 错误码
private final String code;
public BusinessException(String code, String message) {
super(message);
this.code = code;
}
public String getCode() {
return code;
}
}第三步:编写全局异常处理器
使用@RestControllerAdvice注解可以定义一个全局的异常处理器,拦截所有Controller抛出的异常,统一返回我们定义好的错误结构。
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@RestControllerAdvice
public class GlobalExceptionHandler {
// 处理自定义的业务异常
@ExceptionHandler(BusinessException.class)
public ErrorResponse handleBusinessException(BusinessException e) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
return new ErrorResponse(e.getCode(), e.getMessage(), request.getRequestURI());
}
// 处理参数校验异常,比如@Valid注解校验失败
@ExceptionHandler(MethodArgumentNotValidException.class)
public ErrorResponse handleValidException(MethodArgumentNotValidException e) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// 获取第一个校验失败的提示信息
String message = e.getBindingResult().getFieldError().getDefaultMessage();
return new ErrorResponse("PARAM_ERROR", message, request.getRequestURI());
}
// 处理其他未捕获的异常,作为兜底处理
@ExceptionHandler(Exception.class)
public ErrorResponse handleOtherException(Exception e) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// 生产环境不建议返回具体异常信息,避免泄露内部细节
return new ErrorResponse("SYSTEM_ERROR", "系统繁忙,请稍后再试", request.getRequestURI());
}
}实际使用示例
在Controller中如果需要返回业务错误,直接抛出自定义的业务异常即可,不需要自己写try-catch处理。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/users/{id}")
public String getUserById(@PathVariable Long id) {
// 模拟用户不存在的场景
if (id == null || id <= 0) {
throw new BusinessException("USER_NOT_FOUND", "用户不存在");
}
return "用户详情数据";
}
}注意事项
- 生产环境的全局异常兜底处理,不要返回具体的异常堆栈或者详细信息,避免泄露服务内部逻辑
- 错误码可以提前定义成常量或者枚举,方便统一管理,不要硬编码在代码里
- 如果项目有参数校验的需求,可以结合@Valid注解和MethodArgumentNotValidException的处理,减少重复的校验逻辑
- 针对特殊的异常比如权限异常、404异常,可以单独写对应的异常处理方法,返回更明确的错误提示
Spring_BootREST_API异常处理全局异常自定义异常修改时间:2026-05-30 23:46:20