自定义验证器,用于比较bean的两个字段

时间:2015-03-19 19:27:10

标签: spring bean-validation

我想创建一个自定义验证器来验证名为description的字段。此字段的验证依赖于此bean中称为category的另一个字段 - 如果category是Other,则description不能为null或为空,如果category不是Other,则description必须为null或为空。 我之前没有写过自定义验证器,并希望得到任何帮助。 这就是我到目前为止所拥有的 (1)创建@interface

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; 
import javax.validation.Constraint;
import javax.validation.Payload;
@Target(METHOD, FIELD, ANNOTATION_TYPE )
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy=CategoryDescriptionValidator.class)
public @interface CategoryDescription {
String message() default "{description should be empty when category is not other}";
Class<?>[] groups() default {};
}

(2)创建实现 - 这里我很困惑如何指定被比较的字段是Object的类别和描述字段?

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class CategoryDescriptionValidator implements ConstraintValidator<CategoryDescription,Object>{
@Override
public void initialize(CategoryDescription arg0) {
    // TODO Auto-generated method stub

}
@Override
public boolean isValid(Object arg0, ConstraintValidatorContext arg1) {
    // TODO Auto-generated method stub
    return false;
}

}

(3)在我的bean(InformationBean)中,我应该执行以下操作吗?

 public class InformationBean{
 private String category;
 @CategoryDescriptionValidator 
 private String description;
}

1 个答案:

答案 0 :(得分:2)

由于验证涉及两个对象字段,因此需要将约束放在封闭类上。这是有道理的,因为现在您实际上正在验证(部分)对象,而不是单个字段。所以你必须这样做:

@CategoryDescription
public class InformationBean{
 private String category; 
 private String description;
}

完成后,您现在可以实现isValid()方法。如果验证器只适用于这个特定的类(InformationBean),您可以像这样参数化验证器:

public class CategoryDescriptionValidator implements ConstraintValidator<CategoryDescription ,InformationBean>{
  @Override
  public void initialize(CategoryDescription arg0) {
   // ...
  }

  @Override
  public boolean isValid(InformationBean arg0, ConstraintValidatorContext arg1) {
    // validation code here 
  }
}

正如您所看到的,isValid()的第一个参数是您的bean,因此您可以轻松获取类别和描述并实现正确的验证逻辑。这也是将注释放在类上的原因 - 否则您将无法访问这两个字段。如果注释放在字段上,则只能访问带注释字段的值。

如果您希望验证器适用于任何对象,您仍然可以使用您提供的验证器(使用Object作为第二个通用参数)来执行此操作,但是您必须获取要访问的字段不同的方式(例如使用反射)。

编辑:要在课程上加上@CategoryDescription约束,您需要在约束定义中将@Target(METHOD, FIELD, ANNOTATION_TYPE)更改为@Target(TYPE)