Java Autowired在自定义约束验证器中提供空值
我对Spring是全新的,我已经找到了一些关于这个问题的答案。以下是链接: 我有一个Spring项目,其中我想使用Hibernate验证器进行对象验证。根据我在网上阅读的内容和一些论坛,我尝试注入validator,如下所示:Java Autowired在自定义约束验证器中提供空值,java,spring,validation,spring-mvc,hibernate-validator,Java,Spring,Validation,Spring Mvc,Hibernate Validator,我对Spring是全新的,我已经找到了一些关于这个问题的答案。以下是链接: 我有一个Spring项目,其中我想使用Hibernate验证器进行对象验证。根据我在网上阅读的内容和一些论坛,我尝试注入validator,如下所示: @Bean public Validator validator() { return new LocalValidatorFactoryBean().getValidator(); } public AutowireCapableBeanFact
@Bean
public Validator validator() {
return new LocalValidatorFactoryBean().getValidator();
}
public AutowireCapableBeanFactory getAutowireCapableBeanFactory() {
return autowireCapableBeanFactory;
}
public void setAutowireCapableBeanFactory(AutowireCapableBeanFactory autowireCapableBeanFactory) {
this.autowireCapableBeanFactory = autowireCapableBeanFactory;
}
但无论我在哪里使用
@Autowired
Validator validator;
它采用了Spring的验证器实现,而不是Hibernate的验证器。我不知道如何准确地注入Hibernate验证器,并简单地跨其他类自动连接它,所以我使用了一个便宜的技巧,现在我的Java配置如下所示
@Bean
public Validator validator() {
// ValidatorImpl is Hibernate's implementation of the Validator
return new ValidatorImpl();
}
(如果有人能告诉我如何避免以这种黑客方式获取Hibernate Validator,我将不胜感激。)
但让我们来谈谈这里的主要问题:
下面是自定义验证定义
@Target( { METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER } )
@Retention(RUNTIME)
@Constraint(validatedBy = EmployeeValidator.class)
@Documented
public @interface EmployeeValidation {
String message() default "{constraints.employeeConstraints}";
public abstract Class<?>[] groups() default {};
public abstract Class<? extends Payload>[] payload() default {};
}
@Bean
public Validator validator() {
return new LocalValidatorFactoryBean().getValidator();
}
在您的bean定义中
@Target( { METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER } )
@Retention(RUNTIME)
@Constraint(validatedBy = EmployeeValidator.class)
@Documented
public @interface EmployeeValidation {
String message() default "{constraints.employeeConstraints}";
public abstract Class<?>[] groups() default {};
public abstract Class<? extends Payload>[] payload() default {};
}
@Bean
public Validator validator() {
return new LocalValidatorFactoryBean().getValidator();
}
方法定义中的验证器的类型是什么?您应该确保它从Spring返回javax.validation.Validator
,而不是Validator
允许Spring引导验证器也会导致将SpringConstraint验证数据工厂
传递给Hibernate验证器,从而在约束验证器中启用依赖项注入。您可以通过两种方法解决此问题:
- 尝试使用Spring在验证器上注入服务
- 手动初始化它,覆盖验证器的初始化方法
不久前我也遇到了同样的问题,最后我决定使用第二种选择来避免大量的问题
正如您所指出的,您必须在验证器上定义一个初始化方法,在那里您可以使用ServiceUtils来获取所需的服务bean:
@Autowired
private EmployeeService employeeService;
@Override
public void initialize(EmployeeValidation constraintAnnotation) {
//Use an utility service to get Spring beans
employeeService = ServiceUtils.getEmployeeService();
}
ServiceUtils是一个普通的Springbean,在静态方法中使用对自身的静态引用
@Component
public class ServiceUtils {
private static ServiceUtils instance;
@Autowired
private EmployeeService employeeService;
/* Post constructor */
@PostConstruct
public void fillInstance() {
instance = this;
}
/*static methods */
public static EmployeeService getEmployeeService) {
return instance.employeeService;
}
}
因此,您正在使用Spring注入您需要的服务,但不是以通常的方式。
希望这能有所帮助。我希望这个解决方案能帮助某些人:
@Bean
public Validator validator () {
ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
.configure().constraintValidatorFactory(new SpringConstraintValidatorFactory(autowireCapableBeanFactory))
.buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
return validator;
}
使用SpringConstraintValidatorFactory
初始化验证器,以便注入工作,并将验证器实现提供给Hibernate.class,其工作方式如下:
您选择的库将验证您的对象
您的自定义验证器将能够使用Spring的功能,同时由Hibernate执行验证李>
工作原理:
Hibernate的ConstraintValidatorFactory
不会初始化任何ConstraintValidatorFactory
,除非调用它们,但是SpringConstraintValidatorFactory
通过向其提供AutowireCapableBeanFactory
来初始化
编辑
正如@shabyaschi对injectautowireCapableBeanFactory
的一条评论所述,您可以将方法签名更改为:
Validator validator(final AutowireCapableBeanFactory autowireCapableBeanFactory) {
或者在配置文件中为其添加getter和setter,如下所示:
@Bean
public Validator validator() {
return new LocalValidatorFactoryBean().getValidator();
}
public AutowireCapableBeanFactory getAutowireCapableBeanFactory() {
return autowireCapableBeanFactory;
}
public void setAutowireCapableBeanFactory(AutowireCapableBeanFactory autowireCapableBeanFactory) {
this.autowireCapableBeanFactory = autowireCapableBeanFactory;
}
这对我有用。适合现在搜索的人
public class EmployeeValidator implements ConstraintValidator<EmployeeValidation , Object> {
private EmployeeService employeeService;
public EmployeeValidator(EmployeeService employeeService){
this.employeeService = employeeService;
}
...
}
公共类EmployeeValidator实现ConstraintValidator{
私人雇员服务;
公共雇员确认器(雇员服务雇员服务){
this.employeeService=employeeService;
}
...
}
您的代码没有问题,这取决于您是如何创建验证器工厂的。
创建一个bean,让Spring来处理它
@Bean
public ValidatorFactory validatorFactory(){
return Validation.buildDefaultValidatorFactory();
}
您是否需要hibernate验证程序?ValidatorImpl看起来怎么样?@头脑风暴是的,我想要Hibernate验证器,即ValidatorImpl——这就是Hibernate的验证器实现的名称。我不知道你所说的“ValidatorImpl”是什么意思。它是一个实现接口验证程序并遵守其蓝图的具体类。您能显示您的导入语句吗?是spring boot应用程序吗?@brainstorm我只想获得Hibernate验证程序,而不需要将它硬编码到我的Java配置中。因此,基本上无论我在哪里使用以下代码:{@autowiredvalidator Validator;}我希望实现是Hibernate的验证接口实现,而不是Spring的s@brainstorm不,它不是Spring boot应用程序。您希望我从哪个类发布导入语句?我可以编辑这个问题。在我的验证程序配置文件中只有一个导入,我还在返回类型中显式地尝试了javax.validation.Validator。您试过调试它吗?在LocalValidatoryFactoryBean
中,您应该逐步完成将Spring的约束验证器工厂传递给引导验证器的代码。但它首先没有使用Hibernate的验证器。当我从Java配置显式设置Hibernate的验证器时,它采用了Hibernate的ConstraintValidatorFactoryImpl(很明显),我调试并尝试了比我在这里发布的更多的选项。我确实找到了一个解决方案,不过我已经把它作为一个答案贴了出来。我非常感谢你尝试帮助一位程序员同事。谢谢。嗯,好的;奇怪的是,LocalValidatorFactoryBean
默认情况下应该使用SpringConstraintValidatorFactory
。我认为这里有一些通信错误。LocalValidatorFactoryBean确实使用SpringConstraintValidatorFactory。问题是我无法让LocalValidatorFactoryBean返回HIbernate的实现,所以我从配置中手动插入它,但这样做让我将ConstraintValidatorFactoryImpl作为我的ConstraintValidator提供程序,这再次给我带来了问题。于是我决定也推翻这一点。这就是我正在做的,我要求默认使用Hibernate validator,它使用Spring的Constraintfactory。我感谢您的努力,我相信这肯定会奏效,但这是一种黑客方式,可以以更干净的方式完成。我已经看到@Autowired为人们(在论坛上)工作,所以我知道肯定有办法做到这一点。只需要找出它。再次感谢你的邀请