21

我想知道如何在 Spring MVC 应用程序中使用 Spring Validator(不是注释)验证表单中的嵌套对象列表。

class MyForm() {
    String myName;
    List<TypeA> listObjects;
}
class TypeA() {
    String number;
    String value;
}

如何创建 MyFormValidator 来验证 listObjects 并为 TypeA 的数量和值添加错误消息。

4

4 回答 4

27

对于嵌套验证,您可以执行以下操作:

public class MyFormValidator implements Validator {

    private TypeAValidator typeAValidator;

    @Override
    public boolean supports(Class clazz) {
        return MyForm.class.equals(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        MyForm myForm = (MyForm) target;
        typeAValidator = new TypeAValidator();

        int idx = 0;
        for (TypeA item : myForm.getListObjects()) {

            errors.pushNestedPath("listObjects[" + idx + "]");
            ValidationUtils.invokeValidator(this.typeAValidator, item, errors);
            errors.popNestedPath();
            idx++;

            ...
        }

        ...
    }
}

public class TypeAValidator implements Validator{

    @Override
    public boolean supports(Class<?> clazz) {
        return TypeA.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        TypeA objTypeA = (TypeA)target;

        ValidationUtils.rejectIfEmpty(errors, "number", "number.notEmpty");
    }
}

希望这可以帮助。

于 2014-08-14T21:15:26.443 回答
19
public class MyFormValidator implements Validator {

    @Override
    public boolean supports(Class clazz) {
        return MyForm.class.equals(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        MyForm myForm = (MyForm) target;

        for (int i = 0; i < myForm.getListObjects().size(); i++) {
            TypeA typeA = myForm.getListObjects().get(i);

            if(typeAHasAnErrorOnNumber) {
                errors.rejectValue("listObjects[" + i + "].number", "your_error_code");
            }

            ...
        }

        ...
    }

}

有趣的链接:

于 2012-10-01T20:59:14.890 回答
2

我使用的一个方便的助手类 -

public final class ValidationHelper {

    public static <TEntity> void invokeNestedValidator(Validator validator, TEntity entity, Errors errors, String subPath) {
        try {
            errors.pushNestedPath(subPath);
            ValidationUtils.invokeValidator(validator, entity, errors);
        } finally {
            errors.popNestedPath();
        }
    }

    public static <TEntity> void invokeNestedValidatorForList(Validator validator, List<TEntity> entities, Errors errors, String subPathRoot) {
        for (int index = 0; index < entities.size(); index++) {
            invokeNestedValidator(validator, entities.get(index), errors, subPathRoot + "[" + index + "]");
        }
    }

    private ValidationHelper() {}
}
于 2015-08-28T06:51:36.170 回答
1

您可以在项目的任何地方使用它

import org.springframework.validation.ValidationUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections.CollectionUtils;

    public static void invokeValidatorForNestedCollection(Validator validator,
                                                      Object obj,
                                                      String collectionPath,
                                                      Errors errors) {

    Collection collection;
    try {
        collection = (Collection) PropertyUtils.getProperty(obj, collectionPath);
    } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
        throw new RuntimeException(e);
    }

    if (CollectionUtils.isEmpty(collection)) return;
    int counter = 0;
    for (Object elem : collection) {
        errors.pushNestedPath(String.format(collectionPath + "[%d]", counter));
        ValidationUtils.invokeValidator(validator, elem, errors);
        errors.popNestedPath();
        counter++;
    }
}
于 2015-09-30T10:19:19.210 回答