【问题标题】:Spring/Hibernate - validating groups manually and return a BindingResultSpring/Hibernate - 手动验证组并返回 BindingResult
【发布时间】:2013-08-01 07:41:24
【问题描述】:

我想使用组手动验证(不使用@Valid 或@Validated)并返回一个BindingResult。

我配置了一个 spring 验证器

  <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" >
    <property name="validationMessageSource" ref="messageSource"/>
  </bean> 

这是进行验证的类,它可以工作,但请注意 groups 没有被使用。

@Component
public class ObjectValidatorImpl implements ObjectValidator {
    private final Validator validator;

    @Autowired
    public ObjectValidatorImpl(final Validator validator) {
        super();
        this.validator = validator;
    }

    @Override
    public final <T> BindingResult getBindingResults(
               final T objectToValidate, final Class<?>...groups) {
        final DataBinder binder = new DataBinder(objectToValidate);
        binder.setValidator(validator);

        //ideally, I would like to set the groups on the binder here like
        //binder.setGroups(groups);

        binder.validate();
        return binder.getBindingResult();
    }
}

我不知道如何让验证器使用组,这似乎没有办法。

我想这样称呼它。

objectValidator.validate(myObject, Class1.class, Class2.class)

【问题讨论】:

    标签: spring spring-mvc hibernate-validator


    【解决方案1】:

    我遇到了类似的问题,最终扩展了 SpringValidatorAdapter 类,以便我可以执行验证并指定组。

    ExtendedSpringValidatorAdapter adapter = new ExtendedSpringValidatorAdapter(validator);
    adapter.validate(objectToValidate, bindingResult, Class1.class, Class2.class);
    

    这里是扩展验证器的定义:

    package com.example.validator;
    
    import org.springframework.beans.NotReadablePropertyException;
    import org.springframework.validation.Errors;
    import org.springframework.validation.FieldError;
    import org.springframework.validation.beanvalidation.SpringValidatorAdapter;
    
    import javax.validation.ConstraintViolation;
    import javax.validation.Validator;
    import javax.validation.groups.Default;
    import java.util.Set;
    
    public class ExtendedSpringValidatorAdapter extends SpringValidatorAdapter {
    
        // ========================================================================
        // ========================================================================
        // ========================================================================
        public ExtendedSpringValidatorAdapter(Validator targetValidator) {
            super(targetValidator);
        }
    
        // ========================================================================
        // ========================================================================
        // ========================================================================
        public void validate(Object target, Errors errors, Class<?>... groups) {
    
            if (groups == null || groups.length == 0 || groups[0] == null) {
                groups = new Class<?>[]{Default.class};
            }
    
            Set<ConstraintViolation<Object>> result = validate(target, groups);
            for (ConstraintViolation<Object> violation : result) {
                String field = violation.getPropertyPath().toString();
                FieldError fieldError = errors.getFieldError(field);
                if (fieldError == null || !fieldError.isBindingFailure()) {
                    try {
                        errors.rejectValue(field,
                                violation.getConstraintDescriptor().getAnnotation().annotationType().getSimpleName(),
                                getArgumentsForConstraint(errors.getObjectName(), field, violation.getConstraintDescriptor()),
                                violation.getMessage());
                    } catch (NotReadablePropertyException ex) {
                        throw new IllegalStateException("JSR-303 validated property '" + field +
                                "' does not have a corresponding accessor for Spring data binding - " +
                                "check your DataBinder's configuration (bean property versus direct field access)", ex);
                    }
                }
            }
        }
    }
    

    【讨论】:

    • 太棒了,我会在星期一试试这个。
    • 这似乎有点奇怪,但这不是验证器默认行为的一部分。
    • 是的,这很奇怪。这可能是 JSR303 中的一个疏忽。例如,标准的 @Valid 注释不带组,但 spring @Validated 可以(至少在较新的版本中)。
    • BindingResult 不是由 JSR 303 定义的。
    • @John,我无法将验证器传递给ExtendedSpringValidatorAdapter ,因为它是org.springframework.validation.Validator 而不是javax.validation.Validator。另外你从哪里得到Errors errors 对象?你会创建一个像DataBinder binder = new DataBinder(objectToValidate); 这样的新的吗?谢谢
    【解决方案2】:

    我认为最简单的方法是使用SmartValidator。你可以像普通的Validator 一样注入它。通过使用 SmartValidator,您可以获得 Validation Hints,您可以使用它来传递 javax.validation.group 作为参数。而最终的代码可以这么简单:

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.validation.Errors;
    import org.springframework.validation.SmartValidator;
    
    @Component
    public class FooController {
    
        @Autowired
        private SmartValidator validator;
    
        public void validate(MyObject target, Errors errors) {
            validator.validate(target, errors, FirstCheck.class, SecondCheck.class);
        }
    }
    

    【讨论】:

      【解决方案3】:

      3.1版本以来有 org.springframework.validation.DataBinder#validate(java.lang.Object...validationHints)

      那就这样吧:

      binder.validate(Class1.class, Class2.class);
      

      使用了内部方法SmartValidator

      if(... validator instanceof SmartValidator) {
         ((SmartValidator) validator).validate(target, bindingResult, validationHints);
      

      【讨论】:

        猜你喜欢
        • 2016-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-27
        • 2017-07-28
        • 2018-06-20
        • 2019-04-19
        • 1970-01-01
        相关资源
        最近更新 更多