Java Hibernate验证程序-添加动态约束验证程序

Java Hibernate验证程序-添加动态约束验证程序,java,hibernate,validation,annotations,hibernate-mapping,Java,Hibernate,Validation,Annotations,Hibernate Mapping,在了解了之后,我对一个主题产生了兴趣,我是否可以创建一个基本注释,在其中设置要使用的验证器 @Target({ ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = validator().class) public @interface CustomAnnotation { public String message(); Class<?>[] group

在了解了之后,我对一个主题产生了兴趣,我是否可以创建一个基本注释,在其中设置要使用的验证器

@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = validator().class)
public @interface CustomAnnotation {
    public String message();
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    Class<? extends ConstraintValidator<? extends CustomAnnotation, Serializable>> validator();
}

我认为您不能在Hibernate验证器支持的基础上实现动态验证器解析器。最好有一组专用的注释验证器对,这样当您使用特定的验证注释对字段进行注释时,就可以清楚地知道将使用什么验证器了。

我不推荐使用它,但您可以大致这样做:

@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = GenericValidatorBootstrapperValidator.class)
public @interface CustomAnnotation {
    public String message();
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    Class<? extends ConstraintValidator<? extends CustomAnnotation, Serializable>> validator();
}

public class GenericValidatorBootstrapperValidator implements ConstraintValidator<CustomAnnotation, Object> {

    private final ConstraintValidator validator;

    @Override
    public void initialize(CustomAnnotation constraintAnnotation) {
        Class<? extends ConstraintValidator> validatorClass = constraintAnnotation.validator();
        validator = validatorClass.newInstance();
        validator.initialize( ... ); //TODO with what?
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        return validator.isValid(value, context);
    }
}
您甚至可以通过
META/validation.xml
文件将约束注释与实现链接起来

<constraint-mappings
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.1.xsd"
    xmlns="http://jboss.org/xml/ns/javax/validation/mapping" version="1.1">

    <constraint-definition annotation="org.mycompany.CustomAnnotation">
        <validated-by include-existing-validators="true">
            <value>org.mycompany.EnumCustomValidatorImpl</value>
        </validated-by>
    </constraint-definition>
</constraint-mappings>

org.mycompany.EnumCustomValidatorImpl

如果你需要更灵活的方式,我想我最初的建议会奏效。在
genericvalidaterbootstrappervalidator
isValid方法中,您可以根据
value
参数的对象类型调用正确的验证器实例(例如,通过
instanceof
).

Hibernate Validator现在还提供了一个注释,它使自定义验证的实现更加容易,并有助于避免大量代码行

使用示例:

 @ScriptAssert(lang = "javascript", 
    script = "_this.capital.equals(_this.capital.toUpperCase)",
    message = "capital has not Capital letters")
public class BigLetters {

    private String capital;

    public String getCapital() {
        return capital;
    }

    public void setCapital(String capital) {
        this.capital = capital;
    }

}

即使相关注释之间的差异是要验证的数据(即,值在枚举或迭代中)?也可以将
@CustomAnnotation.message()
的值设置为
GenericValidatorBootstrapperValidator.initialize()
?Hi@KaidoShugo,我想我不理解你的问题:)你在谈论哪个枚举或迭代?此外,由于提供了注释本身,GenericValidatorBootstrapperValidator.initialize()也可以使用CustomAnnotation.message()。顺便说一句,注释不能子类化。这就是你一开始想做的吗?这在Java中是不可行的。我将尝试创建一个Bitbucket存储库来解释我的问题。但基本上,问题是创建一个
@CustomAnnotation
,其中可以按照问题中的格式将验证器设置为参数。因为我几乎有几个验证器,其中唯一的区别是要从中进行验证的数据源(例如,枚举、列表、表等)。这就是我当前的实现。尽管相关的注释具有几乎相似的验证,但在待验证数据的值上存在差异?我希望这可以通过注释上的抽象(如果存在的话)来实现。尝试将验证逻辑移动到一个单独的CommonValidator,每个单独的验证器在定义其特定逻辑的同时也将继承CommonValidator逻辑。因此,您是说遵循“Emmanuel Bernard”的实现?Emmanuel是Hibernate验证项目负责人,因此他最清楚。
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {ListValidatorImpl.class, TableValidatorImpl.class, ...})
public @interface CustomAnnotation {
    public String message();
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

public class ListValidatorImpl implements ConstraintValidator<CustomAnnotation, List> {

    @Override
    public boolean isValid(List value, ConstraintValidatorContext context) {
    }
}

public class TableValidatorImpl implements ConstraintValidator<CustomAnnotation, Table> {

    @Override
    public boolean isValid(Table value, ConstraintValidatorContext context) {
    }
}
<constraint-mappings
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.1.xsd"
    xmlns="http://jboss.org/xml/ns/javax/validation/mapping" version="1.1">

    <constraint-definition annotation="org.mycompany.CustomAnnotation">
        <validated-by include-existing-validators="true">
            <value>org.mycompany.EnumCustomValidatorImpl</value>
        </validated-by>
    </constraint-definition>
</constraint-mappings>
 @ScriptAssert(lang = "javascript", 
    script = "_this.capital.equals(_this.capital.toUpperCase)",
    message = "capital has not Capital letters")
public class BigLetters {

    private String capital;

    public String getCapital() {
        return capital;
    }

    public void setCapital(String capital) {
        this.capital = capital;
    }

}