简体   繁体   English

表单验证在 Spring Mvc 应用程序中不起作用

[英]Form validation does not work in Spring Mvc Application

I have a Spring Mvc Application using Spring 5.2.8.RELEASE, which is deployed in a Tomcat 9.0.37 instance.我有一个使用 Spring 5.2.8.RELEASE 的 Spring Mvc 应用程序,它部署在 Tomcat 9.0.37 实例中。

The dependencies section of my pom.xml is the following:我的 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>

My WebConfig class (which is returned in the getServletConfigClasses()) is:我的 WebConfig 类(在 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();
    }
}

I have the following bean that contains some validation constraints:我有以下包含一些验证约束的 bean:

public class User {

    private Long id;

    @NotBlank
    @Size(min = 5, max = 16)
    private String firstName;

    ...
}

I have a JSP file for registering a new user:我有一个用于注册新用户的 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>

The controller that processes the request is the following:处理请求的控制器如下:

@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();
  }
  // ...
}

The validation doesn't get triggered whenever I click the "Register" button in the browser.每当我单击浏览器中的“注册”按钮时,都不会触发验证。

However, when I invoke the method from a unit test, the validation is performed as expected (the test below fails because the redirection is not performed):但是,当我从单元测试调用该方法时,验证按预期执行(下面的测试失败,因为未执行重定向):

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 is in the web package, WebConfig in the config package and User in the package above these two (com.example.myapp). UserController 在 web 包中,WebConfig 在 config 包中,User 在上面这两个包中(com.example.myapp)。

Anyone has any idea what am I doing wrong?任何人都知道我做错了什么?

I have read all related questions on this problem, but wasn't able to find any solution for my problem.我已阅读有关此问题的所有相关问题,但无法为我的问题找到任何解决方案。

You answered your question.你回答了你的问题。

Unit Test works and your form submit doesn't mean Your Data is not been set when you submit Form单元测试有效,您的表单提交并不意味着您提交表单时未设置您的数据

Try this尝试这个

@RequestMapping(value = "/register", method = POST)
public String processRegistration(@Valid @ModelAttribute("user") User user, BindingResult bindingResult) {

If the above doesn't work try adding a log to see if the value is been added to User Object.如果上述方法不起作用,请尝试添加日志以查看该值是否已添加到用户对象。

I eventually managed to figure it out.我最终设法弄明白了。

It was not a code problem, but a project configuration one.这不是代码问题,而是项目配置问题。

After adding some dependencies in the pom.xml (namely hibernate-validator and hibernate-validator-annotation-processor), the corresponding artifacts were not automatically added in the output directory in WEB-INF/lib by IntelliJ IDEA.在pom.xml中添加了一些依赖(即hibernate-validator和hibernate-validator-annotation-processor)后,IntelliJ IDEA并没有在WEB-INF/lib的输出目录中自动添加相应的artifact。

I had to add these libraries manually: https://imgur.com/a/WRkD56F .我必须手动添加这些库: https : //imgur.com/a/WRkD56F

After doing so, the validation works as expected.这样做后,验证按预期工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM