如何在 Spring 4 中打开注释驱动验证?
How to turn on annotation driven validation in Spring 4?
我正在使用如下注释验证:
public String processRegistration(@Valid Spitter spitter, Errors errors,
Model model) {
if (errors.hasErrors()) {
return "registerForm";
}
...
}
但是 errors.hasErrors()
总是 return 错误。我想我没有为注释驱动的验证打开某种开关。但是如何使用 Spring 4 中的 JavaConfig 来实现呢?我尝试将 @AnnotationDrivenConfig
应用于配置 class,但该类型甚至无法解析。
加 1
我已经在 servlet-context.xml
中进行了以下配置,但仍然不起作用。
<annotation-driven />
加 2
spitter.java
:
package com.learnspring.mvc.web;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hibernate.validator.constraints.Email;
public class Spitter {
private Long id;
@NotNull
@Size(min = 5, max = 16)
private String username="default name";
@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;
@NotNull
@Email
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");
}
}
SpitterController.java
package com.learnspring.mvc.web;
import static org.springframework.web.bind.annotation.RequestMethod.*;
import javax.validation.Valid;
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 com.learnspring.mvc.web.Spitter;
import com.learnspring.mvc.web.SpitterRepository;
@Controller
@RequestMapping("/spitter")
public class SpitterController {
private SpitterRepository spitterRepository;
@Autowired
public SpitterController(SpitterRepository spitterRepository) {
this.spitterRepository = spitterRepository;
}
@RequestMapping(value = "/register", method = GET)
public String showRegistrationForm(Model model) {
model.addAttribute("spitter", new Spitter());
return "registerForm";
}
@RequestMapping(value = "/register", method = POST)
public String processRegistration(@Valid Spitter spitter,
Errors errors, Model model) {
if (errors.hasErrors()) {
return "registerForm";
}
if (spitter == null) {
model.addAttribute("ufo", "spitter is null!");
model.addAttribute("mark", "MARKER");
return "forward:/spitter/spitter/registerFail";
}
else if (!spitter.getUsername().contains("ufo")) {
model.addAttribute("ufo", "spitter user name is not ufo!!");
model.addAttribute("mark", "MARKER:" + spitter.getUsername());
model.addAttribute("pwd", "MARKER:" + spitter.getPassword());
return "forward:/spitter/spitter/registerFail";
}
else
return "redirect:/spitter/spitter/registerOK";
}
@RequestMapping(value = "/{username}", method = GET)
public String showSpitterProfile(@PathVariable String username, Model model) {
Spitter spitter = spitterRepository.findByUsername(username);
model.addAttribute(spitter);
return "profile";
}
@RequestMapping(value = "/spitter/registerOK", method = GET)
public String showRegisterOK() {
return "registerOK";
}
@RequestMapping(value = "/spitter/registerFail", method = POST)
public String showRegisterFail() {
return "registerFail";
}
}
registerForm.jsp
:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="f" %>
<%@ page session="false" %>
<html>
<head>
<title>Spitter</title>
<link rel="stylesheet" type="text/css"
href="<c:url value="/resources/style.css" />" >
</head>
<body>
<h1>Register</h1>
<f:form method="POST" commandName="spitter">
f:First Name: <f:input path="firstName" /><br/>
f-Last Name: <f:input path="lastName" /><br/>
f-Email: <f:input path="email" /><br/>
f-User Name: <f:input path="username" /><br/>
f-Password: <f:input path="password" /><br/>
<input type="submit" value="Register" />
</f:form>
</body>
</html>
WebConfig.java
:
package com.learnspring.mvc.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.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan("com.learnspring.mvc.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();
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// TODO Auto-generated method stub
super.addResourceHandlers(registry);
}
}
RootConfig.java
package com.learnspring.mvc.config;
import java.util.regex.Pattern;
import com.learnspring.mvc.config.RootConfig.WebPackage;
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.context.annotation.Import;
import org.springframework.core.type.filter.RegexPatternTypeFilter;
@Configuration
@ComponentScan(basePackages = { "com.learnspring.mvc" }, excludeFilters = { @Filter(type = FilterType.CUSTOM, value = WebPackage.class) })
public class RootConfig {
public static class WebPackage extends RegexPatternTypeFilter {
public WebPackage() {
super(Pattern.compile("com.learnspring.mvc\.web"));
}
}
}
SpitterWebInitialization.java
package com.learnspring.mvc.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import com.learnspring.mvc.config.RootConfig;
import com.learnspring.mvc.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[] { "/" };
}
}
加 3
还有 web.xml
:(实际上,所有内容都被注释掉了。)
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<!--
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
-->
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<!--
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
-->
<!-- Processes application requests -->
<!--
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
-->
</web-app>
根据您的解释和以下错误判断 java.lang.ClassNotFoundException: javax.validation.Validator
Spring 没有看到 类,因此不会启用 JSF-303 验证。
确保正确的 jars 在类路径中并且你也有一个实现。使用 Maven 时,添加如下内容应该可以解决问题。
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.3.Final</version>
</dependency>
这会将所需的 jars 添加到 WEB-INF/lib
目录,这反过来让 Spring Web MVC 检测它并配置适当的 bean。
有关不同注释的解释,您可能需要查看 In Hibernate Validator 4.1+, what is the difference between @NotNull, @NotEmpty, and @NotBlank?。
我在您的代码中看到两点可能会导致问题。
1) 使用正确的命名空间 <mvc:annotation-driven/>
.
而不是 <annotation-driven />
2) 在您的 @Controller
上更改您的函数参数:
public String processRegistration(@Valid Spitter spitter, Errors errors,
Model model) {
if (errors.hasErrors()) {
return "registerForm";
}
...
收件人:
public String processRegistration(@ModelAttribute("spitter") @Valid Spitter spitter, BindingResult result) {
if (result.hasErrors()) {
return "registerForm";
}
...
试试吧! ;)
我正在使用如下注释验证:
public String processRegistration(@Valid Spitter spitter, Errors errors,
Model model) {
if (errors.hasErrors()) {
return "registerForm";
}
...
}
但是 errors.hasErrors()
总是 return 错误。我想我没有为注释驱动的验证打开某种开关。但是如何使用 Spring 4 中的 JavaConfig 来实现呢?我尝试将 @AnnotationDrivenConfig
应用于配置 class,但该类型甚至无法解析。
加 1
我已经在 servlet-context.xml
中进行了以下配置,但仍然不起作用。
<annotation-driven />
加 2
spitter.java
:
package com.learnspring.mvc.web;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hibernate.validator.constraints.Email;
public class Spitter {
private Long id;
@NotNull
@Size(min = 5, max = 16)
private String username="default name";
@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;
@NotNull
@Email
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");
}
}
SpitterController.java
package com.learnspring.mvc.web;
import static org.springframework.web.bind.annotation.RequestMethod.*;
import javax.validation.Valid;
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 com.learnspring.mvc.web.Spitter;
import com.learnspring.mvc.web.SpitterRepository;
@Controller
@RequestMapping("/spitter")
public class SpitterController {
private SpitterRepository spitterRepository;
@Autowired
public SpitterController(SpitterRepository spitterRepository) {
this.spitterRepository = spitterRepository;
}
@RequestMapping(value = "/register", method = GET)
public String showRegistrationForm(Model model) {
model.addAttribute("spitter", new Spitter());
return "registerForm";
}
@RequestMapping(value = "/register", method = POST)
public String processRegistration(@Valid Spitter spitter,
Errors errors, Model model) {
if (errors.hasErrors()) {
return "registerForm";
}
if (spitter == null) {
model.addAttribute("ufo", "spitter is null!");
model.addAttribute("mark", "MARKER");
return "forward:/spitter/spitter/registerFail";
}
else if (!spitter.getUsername().contains("ufo")) {
model.addAttribute("ufo", "spitter user name is not ufo!!");
model.addAttribute("mark", "MARKER:" + spitter.getUsername());
model.addAttribute("pwd", "MARKER:" + spitter.getPassword());
return "forward:/spitter/spitter/registerFail";
}
else
return "redirect:/spitter/spitter/registerOK";
}
@RequestMapping(value = "/{username}", method = GET)
public String showSpitterProfile(@PathVariable String username, Model model) {
Spitter spitter = spitterRepository.findByUsername(username);
model.addAttribute(spitter);
return "profile";
}
@RequestMapping(value = "/spitter/registerOK", method = GET)
public String showRegisterOK() {
return "registerOK";
}
@RequestMapping(value = "/spitter/registerFail", method = POST)
public String showRegisterFail() {
return "registerFail";
}
}
registerForm.jsp
:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="f" %>
<%@ page session="false" %>
<html>
<head>
<title>Spitter</title>
<link rel="stylesheet" type="text/css"
href="<c:url value="/resources/style.css" />" >
</head>
<body>
<h1>Register</h1>
<f:form method="POST" commandName="spitter">
f:First Name: <f:input path="firstName" /><br/>
f-Last Name: <f:input path="lastName" /><br/>
f-Email: <f:input path="email" /><br/>
f-User Name: <f:input path="username" /><br/>
f-Password: <f:input path="password" /><br/>
<input type="submit" value="Register" />
</f:form>
</body>
</html>
WebConfig.java
:
package com.learnspring.mvc.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.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan("com.learnspring.mvc.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();
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// TODO Auto-generated method stub
super.addResourceHandlers(registry);
}
}
RootConfig.java
package com.learnspring.mvc.config;
import java.util.regex.Pattern;
import com.learnspring.mvc.config.RootConfig.WebPackage;
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.context.annotation.Import;
import org.springframework.core.type.filter.RegexPatternTypeFilter;
@Configuration
@ComponentScan(basePackages = { "com.learnspring.mvc" }, excludeFilters = { @Filter(type = FilterType.CUSTOM, value = WebPackage.class) })
public class RootConfig {
public static class WebPackage extends RegexPatternTypeFilter {
public WebPackage() {
super(Pattern.compile("com.learnspring.mvc\.web"));
}
}
}
SpitterWebInitialization.java
package com.learnspring.mvc.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import com.learnspring.mvc.config.RootConfig;
import com.learnspring.mvc.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[] { "/" };
}
}
加 3
还有 web.xml
:(实际上,所有内容都被注释掉了。)
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<!--
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
-->
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<!--
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
-->
<!-- Processes application requests -->
<!--
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
-->
</web-app>
根据您的解释和以下错误判断 java.lang.ClassNotFoundException: javax.validation.Validator
Spring 没有看到 类,因此不会启用 JSF-303 验证。
确保正确的 jars 在类路径中并且你也有一个实现。使用 Maven 时,添加如下内容应该可以解决问题。
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.3.Final</version>
</dependency>
这会将所需的 jars 添加到 WEB-INF/lib
目录,这反过来让 Spring Web MVC 检测它并配置适当的 bean。
有关不同注释的解释,您可能需要查看 In Hibernate Validator 4.1+, what is the difference between @NotNull, @NotEmpty, and @NotBlank?。
我在您的代码中看到两点可能会导致问题。
1) 使用正确的命名空间 <mvc:annotation-driven/>
.
<annotation-driven />
2) 在您的 @Controller
上更改您的函数参数:
public String processRegistration(@Valid Spitter spitter, Errors errors,
Model model) {
if (errors.hasErrors()) {
return "registerForm";
}
...
收件人:
public String processRegistration(@ModelAttribute("spitter") @Valid Spitter spitter, BindingResult result) {
if (result.hasErrors()) {
return "registerForm";
}
...
试试吧! ;)