表单验证在 Spring Mvc 应用程序中不起作用
Form validation does not work in Spring Mvc Application
我有一个使用 Spring 5.2.8.RELEASE 的 Spring Mvc 应用程序,它部署在 Tomcat 9.0.37 实例中。
我的 pom.xml 的依赖项部分如下:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.8.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.1</version>
<type>maven-plugin</type>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.5.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>6.1.5.Final</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
我的 WebConfig class(在 getServletConfigClasses() 中返回)是:
@Configuration
@EnableWebMvc
@ComponentScan({"com.example.myapp.web", "com.example.myapp.data"})
public class WebConfig implements WebMvcConfigurer {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
我有以下包含一些验证约束的 bean:
public class User {
private Long id;
@NotBlank
@Size(min = 5, max = 16)
private String firstName;
...
}
我有一个 JSP 文件用于注册新用户:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf" %>
<%@ page session="false" %>
<html>
<head>
<title>User</title>
</head>
<body>
<h1>Register</h1>
<sf:form method="POST" modelAttribute="user">
First Name: <sf:input path="firstName"/><br/>
<!-- other fields -->
<input type="submit" value="Register"/>
</sf:form>
</body>
</html>
处理请求的控制器如下:
@Controller
@RequestMapping("/user")
public class UserController {
// ...
@RequestMapping(value = "/register", method = POST)
public String processRegistration(@Valid User user, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "registerForm";
}
userRepository.save(user);
return "redirect:/user/" + user.getUsername();
}
// ...
}
每当我在浏览器中单击“注册”按钮时,都不会触发验证。
但是,当我从单元测试调用该方法时,验证按预期执行(以下测试失败,因为未执行重定向):
public class UserControllerTest {
@Test
public void shouldProcessRegistration() throws Exception {
UserRepository mockRepository = mock(UserRepository.class);
User unsaved = new User("John", "Doe", "jdoe", "pass");
User saved = new User(1L, "John", "Doe", "jdoe", "pass");
when(mockRepository.save(unsaved)).thenReturn(saved);
UserController controller = new UserController(mockRepository);
MockMvc mockMvc = standaloneSetup(controller).build();
mockMvc.perform(post("/user/register")
.param("firstName", "John")
.param("lastName", "Doe")
.param("username", "jdoe")
.param("password", "pass"))
.andExpect(redirectedUrl("/user/jdoe"));
verify(mockRepository, atLeastOnce()).save(unsaved);
}
}
UserController在web包里,WebConfig在config包里,User在上面这两个包里(com.example.myapp)。
有人知道我做错了什么吗?
我已经阅读了关于这个问题的所有相关问题,但找不到解决我的问题的方法。
您回答了您的问题。
单元测试有效,您的表单提交并不意味着您在提交表单时未设置您的数据
试试这个
@RequestMapping(value = "/register", method = POST)
public String processRegistration(@Valid @ModelAttribute("user") User user, BindingResult bindingResult) {
如果上述方法不起作用,请尝试添加日志以查看该值是否已添加到用户对象。
我终于想通了。
不是代码问题,是项目配置问题
在pom.xml添加了一些依赖后(即hibernate-validator和hibernate-validator-annotation-processor),在[=21]的输出目录中没有自动添加相应的工件=] 由 IntelliJ IDEA 提供。
我必须手动添加这些库:https://imgur.com/a/WRkD56F。
执行此操作后,验证按预期工作。
我有一个使用 Spring 5.2.8.RELEASE 的 Spring Mvc 应用程序,它部署在 Tomcat 9.0.37 实例中。
我的 pom.xml 的依赖项部分如下:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.8.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.1</version>
<type>maven-plugin</type>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.5.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>6.1.5.Final</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
我的 WebConfig class(在 getServletConfigClasses() 中返回)是:
@Configuration
@EnableWebMvc
@ComponentScan({"com.example.myapp.web", "com.example.myapp.data"})
public class WebConfig implements WebMvcConfigurer {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
我有以下包含一些验证约束的 bean:
public class User {
private Long id;
@NotBlank
@Size(min = 5, max = 16)
private String firstName;
...
}
我有一个 JSP 文件用于注册新用户:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf" %>
<%@ page session="false" %>
<html>
<head>
<title>User</title>
</head>
<body>
<h1>Register</h1>
<sf:form method="POST" modelAttribute="user">
First Name: <sf:input path="firstName"/><br/>
<!-- other fields -->
<input type="submit" value="Register"/>
</sf:form>
</body>
</html>
处理请求的控制器如下:
@Controller
@RequestMapping("/user")
public class UserController {
// ...
@RequestMapping(value = "/register", method = POST)
public String processRegistration(@Valid User user, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "registerForm";
}
userRepository.save(user);
return "redirect:/user/" + user.getUsername();
}
// ...
}
每当我在浏览器中单击“注册”按钮时,都不会触发验证。
但是,当我从单元测试调用该方法时,验证按预期执行(以下测试失败,因为未执行重定向):
public class UserControllerTest {
@Test
public void shouldProcessRegistration() throws Exception {
UserRepository mockRepository = mock(UserRepository.class);
User unsaved = new User("John", "Doe", "jdoe", "pass");
User saved = new User(1L, "John", "Doe", "jdoe", "pass");
when(mockRepository.save(unsaved)).thenReturn(saved);
UserController controller = new UserController(mockRepository);
MockMvc mockMvc = standaloneSetup(controller).build();
mockMvc.perform(post("/user/register")
.param("firstName", "John")
.param("lastName", "Doe")
.param("username", "jdoe")
.param("password", "pass"))
.andExpect(redirectedUrl("/user/jdoe"));
verify(mockRepository, atLeastOnce()).save(unsaved);
}
}
UserController在web包里,WebConfig在config包里,User在上面这两个包里(com.example.myapp)。
有人知道我做错了什么吗?
我已经阅读了关于这个问题的所有相关问题,但找不到解决我的问题的方法。
您回答了您的问题。
单元测试有效,您的表单提交并不意味着您在提交表单时未设置您的数据
试试这个
@RequestMapping(value = "/register", method = POST)
public String processRegistration(@Valid @ModelAttribute("user") User user, BindingResult bindingResult) {
如果上述方法不起作用,请尝试添加日志以查看该值是否已添加到用户对象。
我终于想通了。
不是代码问题,是项目配置问题
在pom.xml添加了一些依赖后(即hibernate-validator和hibernate-validator-annotation-processor),在[=21]的输出目录中没有自动添加相应的工件=] 由 IntelliJ IDEA 提供。
我必须手动添加这些库:https://imgur.com/a/WRkD56F。
执行此操作后,验证按预期工作。