You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何运行自定义Spring Validator需依赖Hibernate Validator?

自定义Spring Validator不生效,必须添加Hibernate Validator才正常

我写了一个自定义Spring Validator用来校验UserRegistrationDTO类,但不管用@Valid注解、数据绑定器校验还是直接调用validate方法,都触发不了校验逻辑。我已经引入了spring-boot-starter-validation依赖,但只有添加Hibernate Validator依赖后校验才正常工作,想知道为什么spring-boot-starter-validation满足不了需求。


依赖配置

初始引入的依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

额外添加的Hibernate Validator依赖

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>8.0.0.Final</version>
</dependency>

DTO类

@Getter @Setter
public class UserRegistrationDTO {
    private String username;
    private String password;
    private String confirmPassword;
    private String email;
}

自定义Validator类

@Component(value = "userRegistrationValidator")
public class UserRegistrationValidator implements Validator {
    @Override
    public boolean supports(Class<?> clazz) {
        return UserRegistrationDTO.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        UserRegistrationDTO userRegistrationDTO = (UserRegistrationDTO) target;
        ValidationUtils.rejectIfEmptyOrWhitespace(errors,"password", "password.empty", "The password must not be empty");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors,"confirmPassword", "cpassword.empty", "You have to confirm you password");

        if (userRegistrationDTO.getPassword() != null) {
            if (userRegistrationDTO.getPassword().length() < 5 || userRegistrationDTO.getPassword().length() > 25)
                errors.rejectValue("password", "password.size", "The password size must be between 5 to 25");

            if (userRegistrationDTO.getConfirmPassword() != null && !userRegistrationDTO.getPassword().equals(userRegistrationDTO.getConfirmPassword()))
                errors.rejectValue("confirmPassword", "password.not_equals", "The password is not equals");
        }
    }
}

Controller类(最终手动调用版本)

@Controller
@RequestMapping("/register")
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class RegisterController {

    @Qualifier("userRegistrationValidator")
    private final Validator validator;

    @PostMapping
    public String registerProcessing(@ModelAttribute("userRegistration") @RequestBody UserRegistrationDTO userRegistrationDTO, BindingResult bindingResult) {
        
        ValidationUtils.invokeValidator(validator, userRegistrationDTO, bindingResult);

        if (bindingResult.hasErrors()) {
            return "login/signup";
        }

        // ... 业务逻辑

        return "redirect:/login";
    }
}

之前尝试的无效方案

  • 方案一:通过数据绑定器添加校验器

    @Qualifier("userRegistrationValidator")
    private final Validator validator;
    
    @InitBinder
    public void initBinder(WebDataBinder webDataBinder) {
        webDataBinder.addValidators(validator);
    }
    

    配合@Valid注解使用,但校验未触发。

  • 方案二:直接调用validate方法

    @PostMapping
    public String registerProcessing(@ModelAttribute("userRegistration") @RequestBody UserRegistrationDTO userRegistrationDTO, BindingResult bindingResult) {
        validator.validate(userRegistrationDTO, bindingResult);
        if (bindingResult.hasErrors()) {
            return "login/signup";
        }
    // ... 业务逻辑
    }
    

    校验逻辑依然未生效。


问题原因

  1. API与实现的分离:spring-boot-starter-validation在Spring Boot 3.x及以上版本中,默认只引入Jakarta Validation API(规范定义),不包含具体实现。Hibernate Validator是Jakarta Validation的官方实现,没有它的话,Spring的校验体系缺少核心执行引擎,连自定义Validator的调用流程都无法正常初始化。
  2. 自动配置的隐性条件:Spring Boot的ValidationAutoConfiguration自动配置类,会在检测到存在校验实现(比如Hibernate Validator)时才会完全初始化校验上下文。如果缺少实现类,自动配置逻辑会部分失效,导致自定义Validator无法被纳入执行链。
  3. 依赖冲突或排除:如果项目中其他依赖间接排除了Hibernate Validator,也会导致starter无法自动引入它。

解决办法

  1. 优先用starter管理版本:不需要手动指定Hibernate Validator的版本,spring-boot-starter-validation会根据Spring Boot版本自动匹配兼容的Hibernate Validator版本,避免版本冲突。如果starter没自动引入,检查是否有依赖排除了Hibernate Validator。
  2. 验证自动配置状态:启动项目时添加--debug参数,查看自动配置报告,确认ValidationAutoConfiguration是否生效。如果失效,排查是否有自定义配置覆盖了自动配置逻辑。
  3. 确认Validator注入正确性:确保UserRegistrationValidator被Spring正确扫描(所在包被@ComponentScan覆盖),Controller中@Qualifier指定的名称和@Component的value完全匹配。

内容的提问来源于stack exchange,提问作者Victor Hugo Pongolino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 01:28:14