Hibernate Validator 泛型和跨参数约束参数传递
Hibernate Validator generic and cross-parameter constraint parameter passing
我想检查 startDate 字段中的值是否是 "before" endDate 字段的值。
这是我的 Bean class:
@AfterStartDate({"startOfDilation","endOfDilation"})
public class MyBean{
private Date startDate,
private Date stopDate,
...
}
注释给出了错误"Cannot find method value
"。我的定义对吗?我也想将此注释用于其他 bean classes。所以,这就是为什么我不想使用 MyBean class 将值传递给 Annotation class.
AfterStartDate.java
@Target({ ElementType.METHOD, ElementType.CONSTRUCTOR,ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = AfterStartDateValidator.class)
public @interface AfterStartDate {
String message() default "{AfterStartDate.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
AfterStartDateValidator.java
@SupportedValidationTarget(ValidationTarget.PARAMETERS)
public class AfterStartDateValidator implements ConstraintValidator<AfterStartDate,Object[]> {
@Override
public void initialize(AfterStartDate constraintAnnotation) {
}
@Override
public boolean isValid(Object[] value, ConstraintValidatorContext context){
if ( value.length != 2 ) {
throw new IllegalArgumentException( "Illegal method signature" );
}
//leave null-checking to @NotNull on individual parameters
if ( value[0] == null || value[1] == null ) {
return true;
}
if ( !( value[0] instanceof Date ) || !( value[1] instanceof Date ) ) {
throw new IllegalArgumentException(
"Illegal method signature, expected two " +
"parameters of type Date."
);
}
return ( (Date) value[0] ).before( (Date) value[1] );
}
}
因此,您的 IDE 问题是您为注释定义了一个值,但没有在注释中定义 value() 属性。
但这是你不那么紧迫的问题。
您想要的是 class 级别约束,并且您使用的是交叉参数,希望它能满足您的要求。不会的。
做你想做的事,你需要:
- 定义一个class级别约束(https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/?v=6.0#section-class-level-constraints)
- 如果您不希望 class 级别约束直接使用您的 bean getter 并且是通用的,您可以将属性定义为注释的 value(),就像您所做的那样(但显然,您需要在注释中声明一个 value() 属性)
- 然后从 value() 中定义的 属性 名称,您需要使用反射从使用 属性 名称的 bean 中提取值。有关反射的基础知识,请参阅此处的教程:https://docs.oracle.com/javase/tutorial/reflect/member/fieldValues.html
我想检查 startDate 字段中的值是否是 "before" endDate 字段的值。 这是我的 Bean class:
@AfterStartDate({"startOfDilation","endOfDilation"})
public class MyBean{
private Date startDate,
private Date stopDate,
...
}
注释给出了错误"Cannot find method value
"。我的定义对吗?我也想将此注释用于其他 bean classes。所以,这就是为什么我不想使用 MyBean class 将值传递给 Annotation class.
AfterStartDate.java
@Target({ ElementType.METHOD, ElementType.CONSTRUCTOR,ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = AfterStartDateValidator.class)
public @interface AfterStartDate {
String message() default "{AfterStartDate.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
AfterStartDateValidator.java
@SupportedValidationTarget(ValidationTarget.PARAMETERS)
public class AfterStartDateValidator implements ConstraintValidator<AfterStartDate,Object[]> {
@Override
public void initialize(AfterStartDate constraintAnnotation) {
}
@Override
public boolean isValid(Object[] value, ConstraintValidatorContext context){
if ( value.length != 2 ) {
throw new IllegalArgumentException( "Illegal method signature" );
}
//leave null-checking to @NotNull on individual parameters
if ( value[0] == null || value[1] == null ) {
return true;
}
if ( !( value[0] instanceof Date ) || !( value[1] instanceof Date ) ) {
throw new IllegalArgumentException(
"Illegal method signature, expected two " +
"parameters of type Date."
);
}
return ( (Date) value[0] ).before( (Date) value[1] );
}
}
因此,您的 IDE 问题是您为注释定义了一个值,但没有在注释中定义 value() 属性。
但这是你不那么紧迫的问题。
您想要的是 class 级别约束,并且您使用的是交叉参数,希望它能满足您的要求。不会的。
做你想做的事,你需要:
- 定义一个class级别约束(https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/?v=6.0#section-class-level-constraints)
- 如果您不希望 class 级别约束直接使用您的 bean getter 并且是通用的,您可以将属性定义为注释的 value(),就像您所做的那样(但显然,您需要在注释中声明一个 value() 属性)
- 然后从 value() 中定义的 属性 名称,您需要使用反射从使用 属性 名称的 bean 中提取值。有关反射的基础知识,请参阅此处的教程:https://docs.oracle.com/javase/tutorial/reflect/member/fieldValues.html