我有一个复杂的对象,其中包含两个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
?
感谢您的帮助。
答案 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
字符串。如果有人知道更好的方式,我会很高兴知道它。感谢