春季-使用JSR-303和自定义验证

尊敬的Spring社区,

我正在尝试实现以下内容

>我希望每个控制器都有一个自定义验证器(via @InitBinder)
>我想让Spring调用validator.validate()(所以not this way)
>我想为此使用JSR-303 @Valid注释
>要验证的bean(RegistrationForm)没有任何按字段的JSR-303批注
>我不想在类路径中包含验证实现(例如Hibernate);从上面的声明中将是无用的

我基本上遵循here所述的步骤:

>我将javax.validation.validation-api:validation-api添加为我的依赖项
>我使用< mvc:注释驱动/>
>我用@Valid标记我的模型:
公共字符串onRegistrationFormSubmitted(@modelattribute(“ registrationForm”)@Valid RegistrationForm registrationForm,BindingResult结果)…

因此,发生的情况是验证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)

解决方法是为AnnotationDrivenBeanDefinitionParser定义一个验证器属性

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

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

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

我了解我正在尝试以一种特殊的方式使用该框架,但是如果验证器属性有特殊含义(告诉您不需要解析验证器),社区会说些什么.

<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) {

欢迎任何反馈.

附言从Spring Forum转发.

最佳答案
这也是我在above mentioned forum上的答案/解决方法的转贴.无论如何,我认为在这里也可能有所帮助.

我发现的唯一解决方法是实现自己的@Valid注释,一旦Spring(至少在3.1.1.RELEASE代码库中)仅检查方法参数注释的简单名称(请查看org.springframework.web.method.annotation) .ModelAttributeMethodProcessor类).这样,我不需要将javax.validation.validation-api:validation-api添加到项目的依赖项中,并且不再获取臭名昭著的javax.validation.ValidationException:无法找到默认提供程序.

/**
 * 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});
        }
    }
}

相关文章

Spring Cloud为Spring Boot应用程序提供Netflix OSS集成。 提供的功能模块包括服务发现(Eureka),断路...
Spring Cloud 学习笔记;maven配置;入门学习;基于Spring Boot 实现;服务端配置,客户端配置;
可以毫不夸张地说,这篇文章介绍的 Spring/SpringBoot 常用注解基本已经涵盖你工作中遇到的大部分常用的...
Spring中各种方式进行日期时间处理,有作用于单个实体的,也有作用于全局的,有作用于请求入参的,有作...
跨域资源共享(Cross-origin resource sharing)(CORS)是W3C的标准,大部分的浏览器都实现了这个标准...
Spring Boot使创建基于Spring的应用程序变得轻松,大部分的SpringBoot应用程序都只需要很少的Spring配置...