使用Spring通过条件验证对象字段

时间:2012-11-13 18:09:38

标签: java spring validation

我有一个复杂的对象,其中包含两个UserPropertyForm个对象:

    public class ComplexUserForm {
       int userType;

       @Valid
       UserPropertyForm property1;
       UserPropertyForm property2;
       ...
    }

    public class UserPropertyForm {
       @NotEmpty
       @Length(max = 255)
       private String title;
       @NotEmpty
       @Length(min = 100)
       private String description;
       ...
    }

我每次都需要property1进行验证,因此我将其标记为@Valid
我需要property2仅在userType == 2

时进行验证

有人可以说我是否可以使用property2字段的注释以简单的方式验证UserPropertyForm

感谢您的帮助。

2 个答案:

答案 0 :(得分:4)

You can use this custom annotation above your class.

    @ValidateIfAnotherFieldHasValue(
            fieldName = "userType",
            fieldValue = "2",
            dependFieldName = "property2")
  public class ComplexUserForm {
       int userType;

       @Valid
       UserPropertyForm property1;
       UserPropertyForm property2;

只有在getUserType()。equals(" 2")时才会验证property2。

错误消息将出现在property2.fieldname中,因此您需要 如果要从property2中一起捕获所有错误,则在JSP中<form:errors path="property2.*"/>

public class ValidateIfAnotherFieldHasValueValidator
implements ConstraintValidator<ValidateIfAnotherFieldHasValue, Object> {

private String fieldName;
private String expectedFieldValue;
private String dependFieldName;

@Override
public void initialize(final ValidateIfAnotherFieldHasValue annotation) {
    fieldName          = annotation.fieldName();
    expectedFieldValue = annotation.fieldValue();
    dependFieldName    = annotation.dependFieldName();
}

@Override
public boolean isValid(final Object value, final ConstraintValidatorContext ctx) {

    if (value == null) {
        return true;
    }

    try {
        final String fieldValue       = BeanUtils.getProperty(value, fieldName);
        final Object dependFieldValue = PropertyUtils.getProperty(value, dependFieldName);

        if (expectedFieldValue.equals(fieldValue)) {

            ctx.disableDefaultConstraintViolation();
            ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
            Validator validator = factory.getValidator();

            Set<ConstraintViolation<Object>> errorList = validator.validate(dependFieldValue);

            for(ConstraintViolation<Object> error : errorList) {

                 ctx.buildConstraintViolationWithTemplate(error.getMessageTemplate())
                 .addNode(dependFieldName+"."+error.getPropertyPath())
                 .addConstraintViolation();
            }

            return errorList.isEmpty();
        }

    } catch (final NoSuchMethodException ex) {
        throw new RuntimeException(ex);

    } catch (final InvocationTargetException ex) {
        throw new RuntimeException(ex);

    } catch (final IllegalAccessException ex) {
        throw new RuntimeException(ex);
    }

    return true;
}

}

@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ValidateIfAnotherFieldHasValueValidator.class)
@Documented
public @interface ValidateIfAnotherFieldHasValue {

    String fieldName();
    String fieldValue();
    String dependFieldName();

    String message() default "{ValidateIfAnotherFieldHasValue.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};

    @Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @interface List {
        ValidateIfAnotherFieldHasValue[] value();
    }

}

答案 1 :(得分:1)

我已经设法在表单验证器的validate方法中执行此操作:

public void validate(final Object obj, final Errors errors) {
   final ComplexUserForm form = (ComplexUserForm) obj;
   if (form.getUserType() == 2) {
      ClassValidator<UserPropertyForm> offered2Validator = new ClassValidator<UserPropertyForm>(UserPropertyForm.class);
      InvalidValue[] property2InvalidValues = property2Validator.getInvalidValues(form.getProperty2());
      for (final InvalidValue invalidValue : property2InvalidValues)
         errors.rejectValue("property2." + invalidValue.getPropertyPath(), invalidValue.getMessage(), invalidValue.getMessage());
      }
   }
}

但是在拒绝"property2."字段的某些值时,我必须在值的路径中添加property2字符串。如果有人知道更好的方式,我会很高兴知道它。感谢