前后端分离架构中,前端通过HTTP请求调用后端REST API,异常处理是否合理直接决定了前端能否快速定位问题、给出友好的用户提示。如果后端异常返回格式混乱、状态码不统一,前端需要写大量适配逻辑,反而增加开发成本。下面我们就来看看Spring Boot REST API在前后端分离场景下的最佳异常处理实践。

前后端分离场景下异常处理的核心要求
适合前后端分离的异常处理需要满足几个核心要求:
- 所有异常返回格式统一,包含明确的错误码、错误信息、可选的错误详情
- HTTP状态码使用规范,业务异常和服务器异常区分开
- 敏感信息不暴露,比如数据库报错、堆栈信息不直接返回给前端
- 处理过程可扩展,新增异常类型时不需要修改大量现有代码
自定义异常与错误响应结构
首先我们需要定义统一的错误响应结构,让前端拿到固定格式的返回:
public class ErrorResponse {
// 业务错误码,比如1001代表参数错误
private Integer code;
// 给前端展示的错误提示
private String message;
// 可选的错误详情,比如校验失败的具体字段
private Object detail;
// 响应时间戳
private Long timestamp;
public ErrorResponse(Integer code, String message, Object detail) {
this.code = code;
this.message = message;
this.detail = detail;
this.timestamp = System.currentTimeMillis();
}
// getter和setter省略
}接着定义自定义业务异常,用于区分业务层面的错误和系统层面的错误:
public class BusinessException extends RuntimeException {
// 业务错误码
private Integer code;
// 错误提示
private String message;
// 错误详情
private Object detail;
public BusinessException(Integer code, String message) {
this(code, message, null);
}
public BusinessException(Integer code, String message, Object detail) {
super(message);
this.code = code;
this.message = message;
this.detail = detail;
}
// getter省略
}全局异常处理器实现
Spring Boot提供了@RestControllerAdvice注解,可以很方便地实现全局异常处理,统一拦截所有控制器抛出的异常:
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;
@RestControllerAdvice
public class GlobalExceptionHandler {
// 处理自定义业务异常
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException e) {
ErrorResponse errorResponse = new ErrorResponse(e.getCode(), e.getMessage(), e.getDetail());
// 业务异常一般返回200或者400,根据团队规范调整
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorResponse);
}
// 处理参数校验异常,比如@Valid注解触发的校验失败
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidException(MethodArgumentNotValidException e) {
Map<String, String> errorMap = new HashMap<>();
for (FieldError fieldError : e.getBindingResult().getFieldErrors()) {
errorMap.put(fieldError.getField(), fieldError.getDefaultMessage());
}
ErrorResponse errorResponse = new ErrorResponse(1001, "参数校验失败", errorMap);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorResponse);
}
// 处理其他未捕获的运行时异常,属于系统异常
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<ErrorResponse> handleRuntimeException(RuntimeException e) {
// 系统异常不要返回具体堆栈信息给前端,避免敏感信息泄露
ErrorResponse errorResponse = new ErrorResponse(5000, "系统异常,请联系管理员", null);
// 系统异常返回500状态码
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
}
}常用异常场景处理示例
下面看几个实际开发中的常见场景,如何在接口中使用异常处理:
参数校验场景
在控制器方法中使用@Valid注解触发参数校验,校验失败会自动被全局处理器捕获:
import org.springframework.validation.annotation.Valid;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@PostMapping("/users")
public String createUser(@RequestBody @Valid UserCreateDTO userCreateDTO) {
// 参数校验通过才会执行到这里,否则直接抛出MethodArgumentNotValidException
return "用户创建成功";
}
}对应的DTO类加上校验注解:
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
public class UserCreateDTO {
@NotBlank(message = "用户名不能为空")
private String username;
@NotNull(message = "年龄不能为空")
private Integer age;
// getter和setter省略
}业务异常场景
在业务逻辑中遇到不符合业务规则的情况,直接抛出自定义业务异常:
public class UserService {
public void createUser(UserCreateDTO dto) {
// 模拟判断用户名已存在
if ("test".equals(dto.getUsername())) {
throw new BusinessException(1002, "用户名已存在", null);
}
// 其他业务逻辑
}
}注意事项
在实际使用中还要注意几个点:
- 不要在全局异常处理器中返回过多的错误详情,尤其是系统异常,避免泄露数据库结构、服务器路径等敏感信息
- 错误码要提前规划,形成统一的错误码文档,方便前后端对接时快速定位问题
- 如果需要区分不同客户端的错误提示,可以在ErrorResponse中增加可选的客户端类型字段,根据实际情况返回不同的提示内容
- 测试时要覆盖各种异常场景,确保返回格式和状态码符合预期
Spring_BootREST_API异常处理前后端分离全局异常修改时间:2026-05-30 23:34:30