【问题标题】:Spring Controller double validation for @ModelAttribute object@ModelAttribute 对象的 Spring Controller 双重验证
【发布时间】:2018-05-20 08:35:42
【问题描述】:

我已经用方法实现了控制器:

public Page<EventDto> search(@ModelAttribute @Valid EventsCriteria criteria){...}

它有效。 EventsCriteria 本身没有特殊的单独验证器,因为它具有内部注释检查器,例如 @NotNull @NotEmpty。现在情况发生了变化,只有这个验证器是不够的。所以我添加并注册了相应的服务来验证一些状态。

我希望服务能够像以前一样验证其他复合案例和单一验证。但是像@NotNull @NotEmpty 这样的单个内部注释检查器不再起作用了。

我是否配置错误或无法同时工作(指定的服务和内部检查器)?

我的验证器示例(在 cmets 中被询问)

没有什么特别的,如果你知道春天,所以我错过了这部分,因为我把你的注意力集中在我的问题上。

@Component
public class EventsCriteriaValidator implements Validator {

    public static final String INVALID_RAGE_PARAMETERS_SPECIFIED = "Invalid rage parameters: please specify " +
            "'from' and 'to' or page 'size";

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

    @Override
    public void validate(Object target, Errors errors) {
        EventsCriteria toValidate = (EventsCriteria) target;
        validateComplexRestriction(toValidate, errors);
    }

    private void validateComplexRestriction(EventsCriteria toValidate, Errors errors) {
        if (toValidate.isRangeEmpty() && toValidate.getSize() == 0) {
            errors.rejectValue(SIZE_FIELD, null, INVALID_RAGE_PARAMETERS_SPECIFIED);
        }
    }

}

【问题讨论】:

  • BindingResult bindingResult 在你的控制器方法中添加这个
  • if(bindingResult.hasErrors()){return "errorr"} 在此处检查条件并根据需要作为错误消息或页面返回
  • 你能分享你的自定义验证码吗?
  • @javaguy 我不确定您的请求是否与解决方案相关,但我只是以任何方式添加了它:)

标签: java validation spring-mvc spring-config


【解决方案1】:

假设您的 EventsCriteria 包含两个字段,因此在您的 validate 方法中,您可以使用以下方法验证这些字段:ValidationUtils (org.springframework.validation.ValidationUtils)

 @Override
    public void validate(Object target, Errors errors) {
        EventsCriteria eventsCriteria= (EventsCriteria) target;
        ValidationUtils.rejectIfEmpty(errors, "field1", "eventsCriteria.field1.empty");
        ValidationUtils.rejectIfEmpty(errors, "field2", "eventsCriteria.field2.empty");
    }

在您的 messages.properties

eventsCriteria.field1.empty = Enter a valid value for field 1.
eventsCriteria.field2.empty = Enter a valid value for field 2.

在你的配置类中添加这个bean:

 @Bean
   public MessageSource messageSource() {
      ResourceBundleMessageSource source = new ResourceBundleMessageSource();
      source.setBasename("messages");
      return source;
   }

【讨论】:

  • 是的,这行得通,但它是解决方法。如果默认情况下可以使用相同的行为,我不希望实现行为,因为不好的做法。但感谢您的关注。
【解决方案2】:

已编辑:

如果你想要自定义和默认验证,你可以使用addValidators in initBinder 添加您的自定义验证。这样默认验证不会被删除。

@Controller
public class MyController
{
    @Autowired
    private EventsCriteriaValidator validator;

    @InitBinder
    protected void initBinder(final WebDataBinder binder)
    {
         binder.addValidators(validator);
    }

  public Page<EventDto> search(@ModelAttribute @Valid EventsCriteria   criteria, BindingResult result){

     if (result.hasErrors()) {
        // validation failed

     } else {
        //validation passed   
     }
  }

}

【讨论】:

  • 我需要两个验证购买默认值。我希望他们会因为@Valid 标记而使用两者。
【解决方案3】:

只需让您的Validator 扩展LocalValidatorFactoryBean,然后在您的验证方法中调用super.validate(target, errors),如下所示:

@Override
public void validate(Object target, Errors errors) {
   super.validate(target, errors);

   EventsCriteria toValidate = (EventsCriteria) target;
   validateComplexRestriction(toValidate, errors);
}

【讨论】:

  • LocalValidatorFactoryBean 为你处理注解验证,这不正是你需要的吗?
猜你喜欢
  • 1970-01-01
  • 2019-08-23
  • 2014-06-30
  • 1970-01-01
  • 2018-08-07
  • 2015-09-30
  • 2018-12-05
  • 2020-08-17
  • 2020-01-06
相关资源
最近更新 更多