表单验证在 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

执行此操作后,验证按预期工作。