全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-18 6 分钟 ✍️ juanwangdev

Spring MVC Hibernate Validator

Hibernate Validator是JSR-303 Bean Validation的参考实现,Spring MVC默认集成了此校验框架。

常用校验注解

注解说明示例
@NotNull不能为null@NotNull private String name;
@NotEmpty不能为空(字符串、集合)@NotEmpty private List<String> list;
@NotBlank不能为空白字符串@NotBlank private String name;
@Size长度范围@Size(min=2, max=10) private String name;
@Min最小值@Min(0) private int age;
@Max最大值@Max(150) private int age;
@Range数值范围@Range(min=0, max=100) private int score;
@Pattern正则匹配@Pattern(regexp="\\d+") private String phone;
@Email邮箱格式@Email private String email;
@Length字符串长度@Length(min=6, max=20) private String pwd;

基本使用

Java
@Data
public class UserDTO {

    @NotBlank(message = "用户名不能为空")
    @Size(min = 3, max = 20, message = "用户名长度3-20个字符")
    private String username;

    @NotBlank(message = "密码不能为空")
    @Length(min = 6, max = 20, message = "密码长度6-20个字符")
    private String password;

    @Email(message = "邮箱格式不正确")
    private String email;

    @Min(value = 0, message = "年龄不能小于0")
    @Max(value = 150, message = "年龄不能超过150")
    private Integer age;

    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
    private String phone;
}

Controller校验

Java
@RestController
@RequestMapping("/api/user")
public class UserController {

    @PostMapping
    public User create(@Valid @RequestBody UserDTO dto, BindingResult result) {
        if (result.hasErrors()) {
            throw new ValidationException(result.getAllErrors());
        }
        return userService.create(dto);
    }

    @PostMapping("/simple")
    public User createSimple(@Valid @RequestBody UserDTO dto) {
        // 校验失败会自动抛出MethodArgumentNotValidException
        return userService.create(dto);
    }
}

全局校验异常处理

Java
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, Object>> handleValidation(
            MethodArgumentNotValidException e) {

        List<Map<String, String>> errors = e.getBindingResult()
            .getFieldErrors()
            .stream()
            .map(error -> {
                Map<String, String> err = new HashMap<>();
                err.put("field", error.getField());
                err.put("message", error.getDefaultMessage());
                err.put("rejectedValue", String.valueOf(error.getRejectedValue()));
                return err;
            })
            .collect(Collectors.toList());

        Map<String, Object> response = new HashMap<>();
        response.put("code", 400);
        response.put("message", "参数校验失败");
        response.put("errors", errors);

        return ResponseEntity.badRequest().body(response);
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<Map<String, Object>> handleConstraintViolation(
            ConstraintViolationException e) {

        List<Map<String, String>> errors = e.getConstraintViolations()
            .stream()
            .map(violation -> {
                Map<String, String> err = new HashMap<>();
                err.put("property", violation.getPropertyPath().toString());
                err.put("message", violation.getMessage());
                return err;
            })
            .collect(Collectors.toList());

        Map<String, Object> response = new HashMap<>();
        response.put("code", 400);
        response.put("message", "参数校验失败");
        response.put("errors", errors);

        return ResponseEntity.badRequest().body(response);
    }
}

方法参数校验

Java
@RestController
@RequestMapping("/api")
@Validated
public class ApiController {

    @GetMapping("/user/{id}")
    public User getUser(
            @PathVariable @Min(1) Long id) {
        return userService.findById(id);
    }

    @GetMapping("/search")
    public List<User> search(
            @RequestParam @NotBlank String keyword,
            @RequestParam @Min(1) @Max(100) Integer size) {
        return userService.search(keyword, size);
    }
}

嵌套对象校验

Java
@Data
public class OrderDTO {

    @NotBlank(message = "订单号不能为空")
    private String orderNo;

    @Valid    // 嵌套对象校验
    @NotNull(message = "收货地址不能为空")
    private AddressDTO address;

    @Valid
    @NotEmpty(message = "商品列表不能为空")
    private List<ProductDTO> products;
}

@Data
public class AddressDTO {

    @NotBlank(message = "省份不能为空")
    private String province;

    @NotBlank(message = "城市不能为空")
    private String city;

    @NotBlank(message = "详细地址不能为空")
    private String detail;
}

集合校验

Java
@Data
public class BatchDTO {

    @Valid
    @NotEmpty(message = "列表不能为空")
    @Size(max = 100, message = "最多100条数据")
    private List<UserDTO> users;
}

自定义校验消息

properties
# ValidationMessages.properties
user.name.required=用户名不能为空
user.name.size=用户名长度必须在{min}和{max}之间
user.email.invalid=邮箱格式不正确
Java
@Data
public class UserDTO {

    @NotBlank(message = "{user.name.required}")
    @Size(min = 3, max = 20, message = "{user.name.size}")
    private String username;

    @Email(message = "{user.email.invalid}")
    private String email;
}

手动校验

Java
@Service
public class UserService {

    @Autowired
    private Validator validator;

    public void validate(UserDTO dto) {
        Set<ConstraintViolation<UserDTO>> violations = validator.validate(dto);

        if (!violations.isEmpty()) {
            List<String> messages = violations.stream()
                .map(ConstraintViolation::getMessage)
                .collect(Collectors.toList());
            throw new ValidationException(messages);
        }
    }

    public void validateProperty(UserDTO dto, String propertyName) {
        Set<ConstraintViolation<UserDTO>> violations =
            validator.validateProperty(dto, propertyName);

        if (!violations.isEmpty()) {
            throw new ValidationException(violations.iterator().next().getMessage());
        }
    }
}

快速失败模式

Java
@Configuration
public class ValidatorConfig {

    @Bean
    public Validator validator() {
        ValidatorFactory factory = Validation.byProvider(HibernateValidator.class)
            .configure()
            .failFast(true)    // 遇到第一个错误立即返回
            .buildValidatorFactory();
        return factory.getValidator();
    }
}

自定义校验注解

Java
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PhoneValidator.class)
public @interface Phone {
    String message() default "手机号格式不正确";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

public class PhoneValidator implements ConstraintValidator<Phone, String> {

    private static final Pattern PHONE_PATTERN =
        Pattern.compile("^1[3-9]\\d{9}$");

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null || value.isEmpty()) {
            return true;    // null由@NotBlank处理
        }
        return PHONE_PATTERN.matcher(value).matches();
    }
}

要点总结

  • Hibernate Validator实现JSR-303 Bean Validation规范
  • @Valid触发对象校验,BindingResult获取错误信息
  • 嵌套对象需加@Valid注解
  • 方法参数校验需类上加@Validated
  • 支持国际化消息配置
  • 可自定义校验注解扩展校验规则

📝 发现内容有误?点击此处直接编辑

← 上一篇 Spring MVC 文件大小与类型限制
下一篇 → Spring MVC JSR-303 Bean Validation
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库