Java RESTful API通过@ControllerAdvice与@ExceptionHandler统一映射异常为标准HTTP状态码,并返回结构化ApiError响应体;配合@Valid实现自动参数校验触发400,且生产环境避免泄露敏感错误详情。

Java 中 RESTful API 将异常映射为标准 HTTP 状态码,核心是用 @ControllerAdvice + @ExceptionHandler 统一处理异常,并返回对应状态码和结构化错误响应。
定义统一错误响应体
先设计一个通用的错误响应结构,便于前端解析:
public class ApiError {
private int status;
private String message;
private LocalDateTime timestamp;
public ApiError(HttpStatus status, String message) {
this.status = status.value();
this.message = message;
this.timestamp = LocalDateTime.now();
}
// getter/setter 省略
}
这样能保证所有错误返回 JSON 格式一致,比如:{"status":404,"message":"用户不存在","timestamp":"2024-06-10T15:22:33"}
用 @ControllerAdvice 拦截特定异常
创建全局异常处理器,按异常类型匹配并设置对应状态码:
立即学习“Java免费学习笔记(深入)”;
-
业务异常(如参数校验失败)→ 400 Bad Request:捕获
MethodArgumentNotValidException或自定义的BadRequestException -
资源未找到 → 404 Not Found:捕获
EntityNotFoundException或NoSuchElementException -
系统内部错误 → 500 Internal Server Error:捕获
RuntimeException(兜底),但建议排除已明确处理的异常
示例:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ApiError> handleValidationExceptions(
MethodArgumentNotValidException ex) {
String message = ex.getBindingResult()
.getFieldErrors().stream()
.map(FieldError::getDefaultMessage)
.findFirst().orElse("参数校验失败");
return ResponseEntity.badRequest().body(new ApiError(HttpStatus.BAD_REQUEST, message));
}
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ApiError> handleUserNotFound(UserNotFoundException ex) {
return ResponseEntity.notFound().build(); // 或返回 new ApiError(HttpStatus.NOT_FOUND, ex.getMessage())
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ApiError> handleGenericException(Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiError(HttpStatus.INTERNAL_SERVER_ERROR, "服务器处理出错"));
}
}
配合 Spring Validation 自动触发 400
在 Controller 方法参数上加 @Valid,配合实体类字段上的注解(如 @NotBlank、@Min),Spring 会自动抛 MethodArgumentNotValidException,无需手动 throw。
例如:
public class CreateUserRequest {
@NotBlank(message = "用户名不能为空")
private String username;
@Min(value = 18, message = "年龄不能小于18")
private int age;
// getter/setter
}
@PostMapping("/users")
public User createUser(@Valid @RequestBody CreateUserRequest request) {
return userService.create(request);
}
若请求中 username 为空,直接返回 400 和提示信息。
避免 500 泄露敏感信息
生产环境切勿把堆栈或数据库错误详情直接返回给前端:
- 日志中记录完整异常(用
log.error("API error", ex)) - 响应体只返回用户友好的提示,如“操作失败,请稍后重试”
- 可对不同环境做区分:开发时返回简要原因,生产时固定模糊提示


















