spring boot 全局异常处理捕获参数校验异常的核心做法是:在 controller 方法参数前添加 @valid 或 @validated 注解,并配合 bindingresult 对象或直接使用 @controlleradvice 统一拦截 methodargumentnotvalidexception。当请求参数不符合校验规则时,框架会自动抛出该异常,全局处理器可将其转换为标准的 json 响应返回给前端。

@Validated 与 @Valid 在分组校验中的区别是什么
两者都能触发校验,但 @Validated 支持分组功能,允许对同一实体在不同场景下应用不同的校验规则,而 @Valid 仅执行默认组的所有规则。若需区分新增和修改操作的校验逻辑,应优先使用 @Validated 并指定分组接口。

package com.example.demo;import javax.validation.constraints.NotNull;import javax.validation.constraints.Size;public class UserDTO { @NotNull(groups = Update.class) private Long id; @Size(min = 2, max = 20, groups = Create.class) private String username; public interface Create {} public interface Update {}}
上述代码定义了 UserDTO,其中 id 仅在 Update 分组中非空,username 仅在 Create 分组中检查长度。在 Controller 中使用 @Validated(UserDTO.Create.class) 时,只有 username 的校验生效;若使用 @Validated(UserDTO.Update.class),则只校验 id。这种机制避免了在单一 DTO 中混合不同业务场景的校验约束。
如何自定义全局异常处理器返回标准错误格式
通过实现 @ControllerAdvice 类并重写 @ExceptionHandler 方法,可以统一捕获 MethodArgumentNotValidException,提取所有校验错误信息并封装为统一的 JSON 结构。这样前端无需解析多种异常格式,直接读取错误列表即可展示。

package com.example.demo;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;@RestControllerAdvicepublic class GlobalExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Map<string object> handleValidationExceptions(MethodArgumentNotValidException ex) { Map<string object> errors = new HashMap(); for (FieldError error : ex.getBindingResult().getFieldErrors()) { errors.put(error.getField(), error.getDefaultMessage()); } return errors; }}</string></string>
该处理器拦截 MethodArgumentNotValidException,遍历 BindingResult 中的每个 FieldError,将字段名作为 Key、错误消息作为 Value 存入 Map。最终返回的 JSON 类似 {"username": "must be between 2 and 20 characters"}。这种方式确保了所有校验失败都返回 HTTP 400 状态码和一致的结构化数据。
当校验失败时,未通过校验的字段值是否会被保留在请求体中
是的,即使校验失败导致异常抛出,原始请求体中的数据依然存在于 MethodArgumentNotValidException 的 BindingResult 中,开发者可通过 error.getRejectedValue() 获取未通过校验的原始值。这在需要记录审计日志或提供“部分成功”反馈时非常有用。











