我有一个复杂的对象,其中包含两个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

谢谢你的帮助。

最佳答案

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

}

07-26 00:58