一、自定义全局异常处理器在 Spring Boot 中自定义校验异常的统一处理通常通过RestControllerAdvice全局异常处理器配合ExceptionHandler异常拦截来实现。这样做的好处是当Valid或Validated校验失败时我们不需要在每个 Controller 里写重复的try-catch或if-else逻辑而是由全局处理器统一捕获并向前端返回格式一致、语义清晰的 JSON 错误信息。以下是实现统一异常处理的标准步骤和完整代码示例️ 1. 引入必要的依赖确保你的pom.xml中包含了 Spring Boot 的 Web 和 Validation 启动器Spring Boot 3.x 默认使用jakarta.validationdependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-validation/artifactId /dependency 2. 创建全局异常处理器核心代码新建一个类如GlobalExceptionHandler使用RestControllerAdvice注解。我们需要重点捕获两种最常见的校验异常MethodArgumentNotValidException处理 Controller 层RequestBody参数校验失败如 POST/PUT 请求的 JSON 数据。ConstraintViolationException处理 GET 请求的RequestParam、PathVariable或 Service 层方法参数校验失败。import jakarta.validation.ConstraintViolation; import jakarta.validation.ConstraintViolationException; import org.springframework.http.HttpStatus; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; RestControllerAdvice public class GlobalExceptionHandler { /** * 处理 RequestBody 参数校验失败 (如 POST/PUT 请求) * 异常类型MethodArgumentNotValidException */ // 返回 400 状态码 ExceptionHandler(MethodArgumentNotValidException.class) ResponseStatus(HttpStatus.BAD_REQUEST) public MapString, Object handleValidationExceptions( MethodArgumentNotValidException ex) { MapString, Object response new HashMap(); response.put(code, 400); response.put(message, 参数校验失败); // 提取所有字段的错误信息拼接成易读的格式 String errors ex.getBindingResult().getFieldErrors().stream() .map(fieldError - fieldError.getField() : fieldError.getDefaultMessage()) .collect(Collectors.joining(, )); response.put(errors, errors); return response; } /** * 处理 RequestParam / PathVariable * 或 Service 层方法参数校验失败 (如 GET 请求) * 异常类型ConstraintViolationException */ ExceptionHandler(ConstraintViolationException.class) ResponseStatus(HttpStatus.BAD_REQUEST) public MapString, Object handleConstraintViolationException( ConstraintViolationException ex) { MapString, Object response new HashMap(); response.put(code, 400); response.put(message, 参数校验失败); // 提取异常中的约束违规信息 String errors ex.getConstraintViolations().stream() .map(ConstraintViolation::getMessage) .collect(Collectors.joining(, )); response.put(errors, errors); return response; } /** * 兜底处理捕获其他未处理的系统异常防止直接暴露堆栈信息给前端 */ ExceptionHandler(Exception.class) ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public MapString, Object handleSystemException(Exception ex) { MapString, Object response new HashMap(); response.put(code, 500); response.put(message, 系统内部错误请联系管理员); return response; } } 3. 实际效果演示假设你有一个接收用户注册的 DTO并且加上了校验规则public class UserRegisterDTO { NotBlank(message 用户名不能为空) private String username; NotBlank(message 密码不能为空) Size(min 6, max 16, message 密码长度必须在6到16位之间) private String password; // getter / setter }当前端传入了不合法的 JSON 数据例如{username: , password: 123}时全局异常处理器会自动拦截并返回如下结构化的 JSON{ code: 400, message: 参数校验失败, errors: username: 用户名不能为空, password: 密码长度必须在6到16位之间 } 最佳实践建议统一返回结构在实际的企业级项目中建议将返回的Map替换为一个专门的ApiResponseT泛型类包含 code, message, data 字段这样能让前后端交互的接口规范更加统一。国际化支持如果你的项目需要支持多语言可以在NotBlank(message {user.username.notblank})中使用占位符并配合 Spring Boot 的国际化i18n资源文件如messages_zh.properties,messages_en.properties来动态返回不同语言的错误提示。避免暴露敏感信息在兜底的Exception处理中千万不要直接把ex.getMessage()或堆栈信息返回给前端以免暴露系统内部逻辑或数据库结构。