使用JSR-303进行自定义验证

时间:2012-04-22 20:50:50

标签: spring validation spring-mvc

亲爱的春天社区,

我想要实现的内容如下:

  • 我希望每个控制器都有一个自定义验证器(via @InitBinder
  • 我希望Spring致电validator.validate()(所以not this way
  • 我想使用JSR-303 @Valid注释
  • 要验证的bean(RegistrationForm)没有任何每个字段的JSR-303注释
  • 我不想在类路径中包含验证实现(如Hibernate);从上面的陈述
  • 起它将毫无用处

我基本上按照提到的步骤here

  • 我添加javax.validation.validation-api:validation-api作为我的依赖
  • 我使用<mvc:annotation-driven />
  • 我用@Valid标记我的模型: public String onRegistrationFormSubmitted(@ModelAttribute("registrationForm") @Valid RegistrationForm registrationForm, BindingResult result) ...

那么会发生什么,验证API会尝试找到任何实现并失败:

Caused by: javax.validation.ValidationException: Unable to find a default provider
    at javax.validation.Validation$GenericBootstrapImpl.configure(Validation.java:264)
    at org.springframework.validation.beanvalidation.LocalValidatorFactoryBean.afterPropertiesSet(LocalValidatorFactoryBean.java:183)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)

解决方法是为validator定义AnnotationDrivenBeanDefinitionParser属性:

<bean name="validator" class="org.company.module.RegistrationFormValidator" />

<mvc:annotation-driven validator="validator" />

但这种方法意味着验证器将通过ConfigurableWebBindingInitializer.initBinder()设置为所有控制器。

我理解我正试图以一种特殊的方式使用框架,但社区将会说,如果validator属性有特殊含义,它告诉验证者不需要解析,例如

<mvc:annotation-driven validator="manual" />

特殊待遇:

--- AnnotationDrivenBeanDefinitionParser.java.orig      2011-06-30 14:33:10.287577300 +0200
+++ AnnotationDrivenBeanDefinitionParser.java   2011-06-30 14:34:27.897449000 +0200
@@ -152,6 +152,10 @@

        private RuntimeBeanReference getValidator(Element element, Object source, ParserContext parserContext) {
                if (element.hasAttribute("validator")) {
+                       if ("manual".equals(element.getAttribute("validator"))) {
+                               return null;
+                       }
+
                        return new RuntimeBeanReference(element.getAttribute("validator"));
                }
                else if (jsr303Present) {

欢迎任何反馈。

P.S。从Spring Forum重新发布。

3 个答案:

答案 0 :(得分:2)

这也是above mentioned forum上我的答案/解决方法的转贴。无论如何,我认为它也可能有助于它。

我找到的唯一解决方法是实现我自己的@Valid注释,一旦Spring(至少在3.1.1.RELEASE代码库中)只检查方法参数注释的简单名称(请查看{{1下面的类)。这样,我就不需要将org.springframework.web.method.annotation.ModelAttributeMethodProcessor添加到项目的依赖项中,我就会停止臭名昭着的javax.validation.validation-api:validation-api

javax.validation.ValidationException: Unable to find a default provider

答案 1 :(得分:1)

为什么你不想包含Hibernate Validator? 曾经的JSR规范有一些实现,如果没有任何实现(或提供者),你就无法使用规范。

你能想象在没有任何JDBC驱动程序的情况下使用JDBC吗?在没有提供者的情况下使用JPA?在没有任何容器的情况下使用Servlet?

它是一样的,Hibernate Validator是JSR-303的参考实现,我不知道任何其他实现,但是如果你不喜欢Hibernate Validator,那就去另外一个实现。

答案 2 :(得分:0)

您写道:

  

我添加了javax.validation.validation-api:validation-api作为我的依赖...

     

引起:javax.validation.ValidationException:无法找到默认提供程序

您还需要实现该API。例如Hibernate Validator,它是默认的implmentation。 (与ORM Hibernate无关)

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>4.2.0.Final</version>
</dependency>
相关问题