校验失败时抛出methodargumentnotvalidexception异常;当@requestbody对象校验不通过时,spring mvc直接抛此异常而非执行方法体,全局处理器用@restcontrolleradvice和@exceptionhandler捕获并返回400响应。

Spring Boot 中校验失败后,自动抛出特定异常(如 MethodArgumentNotValidException),全局异常处理器通过 @RestControllerAdvice 捕获它,并统一构造结构化错误响应——这样 Controller 就完全不用写 if (bindingResult.hasErrors()) 这类重复逻辑。
校验失败时抛什么异常?
只要在参数上用了 @Valid 或 @Validated,且校验不通过,Spring MVC 就不会执行方法体,而是直接抛出以下异常之一:
-
MethodArgumentNotValidException:最常见,用于
@RequestBody对象校验失败 -
ConstraintViolationException:多见于
@Validated用在方法参数或@Valid用在非控制器类中 -
BindException:较少见,主要出现在表单提交(
@ModelAttribute)场景
全局处理器怎么捕获并处理?
新建一个带 @RestControllerAdvice 的类,在里面用 @ExceptionHandler 明确声明要处理哪种异常:
- 对
MethodArgumentNotValidException,提取所有字段错误信息,拼成可读提示 - 返回
ResponseEntity<errorresponse></errorresponse>,状态码设为400 BAD_REQUEST - 确保
ErrorResponse包含code、message、details等字段,方便前端解析
实际代码怎么写?
示例片段(精简关键部分):
// 全局异常处理器类@RestControllerAdvicepublic class GlobalExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<errorresponse> handleValidation(MethodArgumentNotValidException e) {</errorresponse> String msg = e.getBindingResult().getFieldErrors().stream() .map(f -> f.getField() + ": " + f.getDefaultMessage()) .collect(Collectors.joining("; ")); return ResponseEntity.badRequest().body( new ErrorResponse(400, "参数校验失败", msg) ); }}
注意事项和常见坑
有些情况会导致校验“看似失效”,其实是因为异常没被正确捕获:
- 没加
@RestControllerAdvice或类不在 Spring 扫描路径下 → 异常直接 500 - Controller 方法里手动 try-catch 了
MethodArgumentNotValidException→ 全局处理器收不到 - 用了
@Validated但没传分组,而字段注解指定了分组 → 校验根本没触发 - DTO 字段用了
@NotNull但传的是空字符串(不是 null)→ 应该用@NotBlank











