【问题标题】:hibernate validator doen't work with Spring MVC application休眠验证器不适用于 Spring MVC 应用程序
【发布时间】:2018-10-12 08:51:02
【问题描述】:

我正在关注 Spring in action 第 4 本书中的一个示例项目。然而,我在第 5 章被阻止了,在那里使用休眠验证器来验证表单提交的值。以下是一些相关代码:

我有一个名为 Spitter 的模型:

package spittr;


import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;


public class Spitter {

    private Long id;

    @NotNull
    @Size(min=5, max=16)
    private String username;

    @NotNull
    @Size(min=5, max=25)
    private String password;

    @NotNull
    @Size(min=2, max=30)
    private String firstName;

    @NotNull
    @Size(min=2, max=30)
    private String lastName;
    private String email;

    public Spitter() {
    }

    public Spitter(String username, String password, String firstName, String lastName, String email) {
        this(null, username, password, firstName, lastName, email);
    }

    public Spitter(Long id, String username, String password, String firstName, String lastName, String email) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public boolean equals(Object that) {
        return EqualsBuilder.reflectionEquals(this, that, "firstName", "lastName", "username", "password", "email");
    }

    @Override
    public int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this, "firstName", "lastName", "username", "password", "email");
    }

}

控制器收集表单数据并验证它们:

package spittr.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import spittr.Spitter;
import spittr.data.SpitterRepository;

import javax.validation.Valid;

@Controller
@RequestMapping("/spitter")
public class SpitterController {

    private SpitterRepository spitterRepository;

    @Autowired
    public SpitterController(SpitterRepository spitterRepository) {
        this.spitterRepository = spitterRepository;
    }


    @RequestMapping(value = "register", method = RequestMethod.POST)
    public String processRegistration(@Valid Spitter spitter, Errors errors) {
        System.out.println(errors.hasErrors() + ": has errors...");
        if (errors.hasErrors()){
            return "registerForm";
        }
        spitterRepository.save(spitter);
        return "redirect:/spitter/" + spitter.getUsername();
    }
}

还有配置文件(基于 Java):

package spittr.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@ComponentScan(
        basePackages = {"spittr"},
        excludeFilters = {
                @Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class)
        })
public class RootConfig {
}

SpitterWebInitializer: 包 spittr.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import spittr.web.WebConfig;

public class SpitterWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[]{RootConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[]{WebConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

}

网络配置 包 spittr.web;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc
@ComponentScan("spittr.web")
public class WebConfig extends WebMvcConfigurerAdapter {

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}

build.gradle 文件:

apply plugin: 'war'
apply plugin: 'idea'
apply plugin: 'java'
//apply from: 'gretty.plugin'
apply plugin: 'com.bmuschko.tomcat'

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'com.bmuschko:gradle-tomcat-plugin:2.2.2'
    }
}

dependencies {
    compile "org.springframework:spring-webmvc:4.0.7.RELEASE"
    compile "org.springframework:spring-jdbc:4.0.7.RELEASE"
    compile "org.hibernate:hibernate-validator:5.3.2.Final"
    //providedCompile "org.glassfish.web:javax.el:2.2.4"
    // https://mvnrepository.com/artifact/javax.validation/validation-api
    providedCompile group: 'javax.validation', name: 'validation-api', version: '1.1.0.Final'

    compile "javax.servlet:jstl:1.2"
    compile "org.apache.commons:commons-lang3:3.1"
    def tomcatVersion = '7.0.59'
    tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
            "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}",
            "org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}"
    providedCompile "javax.servlet.jsp:jsp-api:2.1"
    providedCompile "javax.el:javax.el-api:2.2.4"
    providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
    maven { url 'http://maven.springframework.org/release' }
    maven { url 'http://maven.springframework.org/milestone' }
    maven { url 'http://maven.springframework.org/snapshot' }
    maven { url 'http://download.java.net/maven/2' }
    mavenCentral()

}

war {
    baseName = 'spittr'
    version = '0.1.0'
}

tomcat {
    httpPort = 8080
    httpsPort = 8443
    enableSSL = true
//    contextPath = 'sample-app'
}

GitHub 上提供的完整项目:https://github.com/zmrenwu/Spittr

我花了几天时间在 Google 和 Stackoverflow 上搜索解决方案,但没有运气。

请给我一些帮助,谢谢!

【问题讨论】:

    标签: java spring spring-mvc hibernate-validator


    【解决方案1】:

    我对 Gradle 不熟悉,但我认为如果您删除这一行,它会起作用:

    providedCompile group: 'javax.validation', name: 'validation-api', version: '1.1.0.Final' 
    

    至少我用 Maven 测试过,它解决了这个问题。

    【讨论】:

    • 这会导致一个新问题,似乎与 gradle tomcat 插件有关,我也不知道。
    • 此解决方案也适用于 Gradle,我刚刚对其进行了测试:我已经克隆了您的 Github 存储库。然后我将build.gradle 的内容替换为您在 Stackoverflow 上发布的内容。然后我添加了一堆 @NotNull@Size 注释,正如您在帖子中描述的那样,验证不起作用。但后来我注释掉了这一行,验证工作正常。注意:我使用命令gradle tomcatRun 运行应用程序。
    • 好奇怪,你用的什么gradle版本?
    • 我使用了你的 Github repo 捆绑的 gradle 包装器——显然是 gradle 4.10。
    • 如果我注释掉这一行,然后运行 ​​gradle tomcatRun,我得到了这样的异常:org.springframework.beans.factory.BeanCreationException:在创建类 org.springframework 中定义的名称为 'requestMappingHandlerAdapter' 的 bean 时出错。 web.servlet.config.annotation.DelegatingWebMvcConfiguration:bean 的实例化失败;嵌套异常是 org.springframework.beans.factory.BeanDefinitionStoreException: 工厂方法 [public org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter org.springframework.web.servlet.config.annotation....
    【解决方案2】:

    在你的控制器类中添加@Validated注解:

    @Controller
    @Validated
    @RequestMapping("/spitter")
    public class SpitterController {
    
    ...
    

    【讨论】:

    • 感谢您的建议,但仍然没有运气。
    【解决方案3】:

    hibernate-validator 默认使用 javax.validation:validation-api:jar:1.1.0.Final

    [信息] | +- org.hibernate.validator:hibernate-validator:jar:6.0.12.Final:compile [信息] | | +- (javax.validation:validation-api:jar:1.1.0.Final:

    尝试升级到最新版本 javax.validation:validation-api:2.0.1。最后这对我有用。

    【讨论】:

    • 我升级:编译“org.hibernate:hibernate-validator:6.0.13.Final”,提供编译组:'javax.validation',名称:'validation-api',版本:'2.0. 1.Final',还是不行。
    猜你喜欢
    • 1970-01-01
    • 2019-03-20
    • 2023-03-16
    • 2022-01-20
    • 2020-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多