3

我有一个复杂的对象,其中包含两个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字段的注释以简单的方式进行验证?

谢谢你的帮助。

4

2 回答 2

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 中,因此 <form:errors path="property2.*"/>如果您想从 property2 中捕获所有错误,则需要在 JSP 中。

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();
    }

}
于 2015-10-23T01:19:53.553 回答
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。如果有人知道更好的方法,我会很高兴知道。谢谢

于 2012-11-14T06:36:05.193 回答