Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Autowired在自定义约束验证器中提供空值_Java_Spring_Validation_Spring Mvc_Hibernate Validator - Fatal编程技术网

Java Autowired在自定义约束验证器中提供空值

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

我对Spring是全新的,我已经找到了一些关于这个问题的答案。以下是链接:

我有一个Spring项目,其中我想使用Hibernate验证器进行对象验证。根据我在网上阅读的内容和一些论坛,我尝试注入validator,如下所示:

@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对inject
    autowireCapableBeanFactory
    的一条评论所述,您可以将方法签名更改为:

    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为人们(在论坛上)工作,所以我知道肯定有办法做到这一点。只需要找出它。再次感谢你的邀请