3

亲爱的春天社区,

我要实现的是以下内容:

  • 我希望每个控制器都有一个自定义验证器(通过@InitBinder
  • 我想春天打电话validator.validate()(所以不是这样
  • 我想为此使用 JSR-303@Valid注释
  • 要验证的 bean ( RegistrationForm) 没有任何每个字段的 JSR-303 注释
  • 我不想将验证实现(如Hibernate)包含到类路径中;从上面的陈述来看,这将是无用的

我基本上遵循这里提到的步骤:

  • 我添加javax.validation.validation-api:validation-api为我的依赖项
  • 我用<mvc:annotation-driven />
  • 我用以下标记我的模型@Validpublic 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) {

欢迎任何反馈。

PS 来自Spring 论坛的转贴。

4

3 回答 3

2

这也是我在上述论坛上的答案/解决方法的转贴。无论如何,我认为在这里也可能会有所帮助。

我发现的唯一解决方法是实现我自己的@Valid注释,一旦 Spring(至少在 3.1.1.RELEASE 代码库中)只检查方法参数注释的简单名称(请查看org.springframework.web.method.annotation.ModelAttributeMethodProcessor下面的类)。这样,我不需要添加javax.validation.validation-api:validation-api到我的项目的依赖项中,并且我不再获得臭名昭著的javax.validation.ValidationException: Unable to find a default provider.

/**
 * Validate the model attribute if applicable.
 * <p>The default implementation checks for {@code @javax.validation.Valid}.
 * @param binder the DataBinder to be used
 * @param parameter the method parameter
 */
protected void validateIfApplicable(WebDataBinder binder, MethodParameter parameter) {
    Annotation[] annotations = parameter.getParameterAnnotations();
    for (Annotation annot : annotations) {
        if (annot.annotationType().getSimpleName().startsWith("Valid")) {
            Object hints = AnnotationUtils.getValue(annot);
            binder.validate(hints instanceof Object[] ? (Object[]) hints : new Object[] {hints});
        }
    }
}
于 2012-04-22T22:42:24.260 回答
1

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

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

同理,Hibernate Validator 是 JSR-303 的参考实现,我不知道有没有其他实现,但是如果你不喜欢 Hibernate Validator,那就换个实现吧。

于 2012-04-22T21:19:28.730 回答
0

你写了:

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

原因:javax.validation.ValidationException:找不到默认提供程序

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

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>4.2.0.Final</version>
</dependency>
于 2012-04-22T21:12:16.283 回答