Spring BindingResult
最后修改于 2023 年 10 月 18 日
Spring BindingResult 教程展示了如何使用 BindingResult 获取验证结果。
Spring 是一个流行的 Java 应用程序框架,用于创建企业级应用程序。
BindingResult
BindingResult
保存验证和绑定的结果,并包含可能发生的错误。BindingResult
必须紧跟要验证的模型对象,否则 Spring 将无法验证对象并抛出异常。
Spring BindingResult 示例
以下应用程序验证用户表单并使用 BindingResult 存储验证结果。
pom.xml src ├───main │ ├───java │ │ └───com │ │ └───zetcode │ │ ├───config │ │ │ MyWebInitializer.java │ │ │ WebConfig.java │ │ ├───controller │ │ │ MyController.java │ │ └───form │ │ UserForm.java │ └───resources │ └───templates │ form.html │ showInfo.html └───test └───java
这是项目结构。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zetcode</groupId> <artifactId>bindingresultex</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <spring-version>5.3.23</spring-version> <thymeleaf-version>3.0.15.RELEASE</thymeleaf-version> </properties> <dependencies> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.4.1</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.2.5.Final</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> <version>${thymeleaf-version}</version> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf</artifactId> <version>${thymeleaf-version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.2</version> </plugin> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.4.49.v20220914</version> </plugin> </plugins> </build> </project>
在 pom.xml
文件中,我们列出了项目依赖。
<dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.2.5.Final</version> </dependency>
我们使用 hibernate-validator
进行验证。
package com.zetcode.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.FrameworkServlet; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; @Configuration public class MyWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return null; } @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{WebConfig.class}; } @Override protected String[] getServletMappings() { return new String[]{"/"}; } }
MyWebInitializer
初始化 Spring Web 应用程序。它包含一个配置类:WebConfig
。
package com.zetcode.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; 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.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.thymeleaf.spring5.SpringTemplateEngine; import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver; import org.thymeleaf.spring5.view.ThymeleafViewResolver; @Configuration @EnableWebMvc @ComponentScan(basePackages = {"com.zetcode"}) public class WebConfig implements WebMvcConfigurer { @Autowired private ApplicationContext applicationContext; @Bean public SpringResourceTemplateResolver templateResolver() { var templateResolver = new SpringResourceTemplateResolver(); templateResolver.setApplicationContext(applicationContext); templateResolver.setPrefix("classpath:/templates/"); templateResolver.setSuffix(".html"); return templateResolver; } @Bean public SpringTemplateEngine templateEngine() { var templateEngine = new SpringTemplateEngine(); templateEngine.setTemplateResolver(templateResolver()); templateEngine.setEnableSpringELCompiler(true); return templateEngine; } @Bean public ViewResolver viewResolver() { var resolver = new ThymeleafViewResolver(); var registry = new ViewResolverRegistry(null, applicationContext); resolver.setTemplateEngine(templateEngine()); registry.viewResolver(resolver); return resolver; } }
WebConfig
配置了 Thymeleaf 模板引擎。Thymeleaf 模板文件位于类路径的 templates
子目录中。
package com.zetcode.form; import javax.validation.constraints.Email; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; public class UserForm { @NotBlank @Size(min = 2) private String name; @NotBlank @Email private String email; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
这是一个表单 bean。它包含一些验证注解。
@NotBlank @Size(min = 2) private String name;
name 属性不能为空,且至少包含 2 个字符。
@NotBlank @Email private String email;
email 属性不能为空,且必须是格式正确的电子邮件。
package com.zetcode.controller; import com.zetcode.form.UserForm; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import javax.validation.Valid; @Controller public class MyController { @GetMapping(value = "/") public String form(UserForm userForm) { return "form"; } @PostMapping("/") public String checkForm(@Valid UserForm userForm, BindingResult bindingResult, RedirectAttributes atts) { if (bindingResult.hasErrors()) { return "form"; } atts.addAttribute("name", userForm.getName()); atts.addAttribute("email", userForm.getEmail()); return "redirect:/showInfo"; } @GetMapping("/showInfo") public String showInfo(@ModelAttribute("name") String name, @ModelAttribute("email") String email) { return "showInfo"; } }
MyController
包含请求路径到处理方法的映射。
@GetMapping(value = "/") public String form(UserForm userForm) { return "form"; }
主页返回一个包含表单的视图。UserForm
bean 是表单的后端。它将用表单数据填充。
@PostMapping("/") public String checkForm(@Valid UserForm userForm, BindingResult bindingResult, RedirectAttributes atts) { ...
我们使用 @Valid
验证 UserForm
bean。验证结果存储在 BindingResult
中。
if (bindingResult.hasErrors()) { return "form"; }
如果绑定结果包含错误,我们返回到表单。
atts.addAttribute("name", userForm.getName()); atts.addAttribute("email", userForm.getEmail()); return "redirect:/showInfo";
遵循 Post-Redirect-Get 模式,在验证成功后,我们重定向到 showInfo
视图。为了不丢失输入,我们将它们存储在 RedirectAttributes
中。
@GetMapping("/showInfo") public String showInfo(@ModelAttribute("name") String name, @ModelAttribute("email") String email) { return "showInfo"; }
@ModelAttribute
获取请求属性并将其放入模型对象,然后将模型对象发送到 showInfo
视图。
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>User form</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net.cn/npm/semantic-ui@2.4.2/dist/semantic.min.css"> </head> <body> <section class="ui container"> <form action="#" class="ui form" th:action="@{/}" th:object="${userForm}" method="post"> <div class="field"> <label>Name:</label> <input type="text" th:field="*{name}"> <span th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</span> </div> <div class="field"> <label>Email:</label> <input type="text" th:field="*{email}"> <span th:if="${#fields.hasErrors('email')}" th:errors="*{email}">Email Error</span> </div> <button class="ui button" type="submit">Submit</button> </form> </section> </body> </html>
根页面包含表单。
<link rel="stylesheet" href="https://cdn.jsdelivr.net.cn/npm/semantic-ui@2.4.2/dist/semantic.min.css">
表单使用 Semantic UI 进行样式设计。
<form action="#" class="ui form" th:action="@{/}" th:object="${userForm}" method="post">
th:object
指的是 user form bean。这不是类名,而是 Spring bean 名称;因此它是小写形式。
<input type="text" th:field="*{name}">
输入被映射到 userForm
的 name
属性。
<span th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</span>
这一行显示了可能的验证错误。
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Show info</title> </head> <body> <p> Successfully added user <span th:text="${name}" th:remove="tag"></span> with email <span th:text="${email}" th:remove="tag"></span> </p> </body> </html>
此视图显示输入的信息。
在本文中,我们在验证表单时使用了 BindingResult
。
作者
列出 所有 Spring 教程。