本文首发于个人网站: Spring Boot 构建的 web 项目如何在服务端校验表单输入 http://www.javaadu.online/?p=633
这个例子用于演示在 Spring Boot 应用中如何验证 Web 应用的输入, 我们将会建立一个简单的 Spring MVC 应用, 来读取用户输入并使用 validation 注解来检查, 并且当用户输入错误时, 应用需要再屏幕上显示错误信息提示用户重新输入.
首先构建 Maven 项目, 该项目的 pom 文件内容如下:
- <?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>org.example</groupId>
- <artifactId>validating-form-input</artifactId>
- <version>1.0-SNAPSHOT</version>
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>1.5.1.RELEASE</version>
- </parent>
- <properties>
- <java.version>1.8</java.version>
- </properties>
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
- <dependencies>
- <!-- thymeleaf 模板, 用于前段渲染 -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-thymeleaf</artifactId>
- </dependency>
- <!-- 用于输入验证 -->
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-validator</artifactId>
- </dependency>
- <!-- 用于支持嵌入式 tomcat -->
- <dependency>
- <groupId>org.apache.tomcat.embed</groupId>
- <artifactId>tomcat-embed-el</artifactId>
- </dependency>
- <!-- 用于 spring boot 应用的测试 -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
- </project>
Spring Boot Maven 插件提供了很多方便的特性:
它将该项目中需要的各个 Jar 包收集起来, 并打包成可直接运行的 Jar 包, 以更方便得部署和传输;
它会搜索包含 "public static void main()" 方法的类, 该类就是可运行 Jar 包的启动类;
它提供了内在的支持, 去匹配 Spring Boot 的版本号.
Form 对象
创建一个 Form 对象, 用于对应 html 页面中输入的对象 --PersonForm,
- package hello;
- import javax.validation.constraints.Min;
- import javax.validation.constraints.NotNull;
- import javax.validation.constraints.Size;
- /**
- * Created by IntelliJ IDEA.
- * User: duqi
- * Date: 2017/2/28
- * Time: 21:53
- */
- public class PersonForm {
- @NotNull
- @Size(min = 2, max = 30)
- private String name;
- @NotNull
- @Min(18)
- private Integer age;
- public String getName() {
- return name;
- }
- public Integer getAge() {
- return age;
- }
- public void setName(String name) {
- this.name = name;
- }
- public void setAge(Integer age) {
- this.age = age;
- }
- public String toString() {
- return "Person(Name:" + this.name + ", Age:" + this.age + ")";
- }
- }
在这里,@NotNull 注解表示该属性不能为空,@Size(min=2, max=30)表示 name 属性的长度在 [2,30] 之间,@Min(18)表示 age 属性最小值为 18.
Web 控制器
编写一个 Web 控制器, 引用为: src/main/java/hello/WebController.java, 代码如下:
- package hello;
- import org.springframework.stereotype.Controller;
- import org.springframework.validation.BindingResult;
- import org.springframework.Web.bind.annotation.GetMapping;
- import org.springframework.Web.bind.annotation.PostMapping;
- import org.springframework.Web.servlet.config.annotation.ViewControllerRegistry;
- import org.springframework.Web.servlet.config.annotation.WebMvcConfigurerAdapter;
- import javax.validation.Valid;
- /**
- * Created by IntelliJ IDEA.
- * User: duqi
- * Date: 2017/3/2
- * Time: 14:07
- */
- @Controller
- public class WebController extends WebMvcConfigurerAdapter {
- @Override
- public void addViewControllers(ViewControllerRegistry registry) {
- registry.addViewController("/results").setViewName("results");
- }
- @GetMapping("/")
- public String showForm(PersonForm personForm) {
- return "form";
- }
- @PostMapping("/")
- public String checkPersonInfo(@Valid PersonForm personForm, BindingResult bindingResult) {
- if (bindingResult.hasErrors()) {
- return "form";
- }
- return "redirect:/results";
- }
- }
在这个控制器中, GET 方法和 POST 方法都映射到 "/"url 下, showForm 方法会返回 "form" 字符串, 表示模板的名称, 视图控制器根据这个字符串查找模板文件 form.HTML, 在 showForm 的方法签名中定义了 PersonForm 参数, 以便模板将属性绑定到 PersonForm 对象的属性中, checkPersonFormInfo 方法定义了两个入参:(1)person 对象, 在这个参数前用 @Valid 修饰, 用于检查从 form 页面提交过来的属性值;(2)bindingResult 对象, 用于存放 @Valid 注解检查的结果.
可以从 PersonForm 表格中提取属性值, 并存入 PersonForm 对象.@Valid 注解会检查这些属性的有效性, 如果有错也会把错误信息渲染到模板中并显示到页面上.
如果所有的属性都通过校验, 该方法会将浏览器重定向到 results 页面.
构建 thymeleaf 页面
spring boot 默认从 src/main/resources/templates 目录下查找 HTML 页面, form.HTML 和 results.HTML 都放在这里.
- <!DOCTYPE HTML>
- <HTML xmlns:th="http://www.thymeleaf.org">
- <head>
- <title>
- Spring Boot Thymeleaf Hello World Example
- </title>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- </head>
- <body>
- <form action="#" th:action="@{/}" th:object="${personForm}" method="post">
- <table>
- <tr>
- <td>
- Name:
- </td>
- <td>
- <input type="text" th:field="*{name}" />
- </td>
- <td th:if="${#fields.hasErrors('name')}" th:errors="*{name}">
- Name Error
- </td>
- </tr>
- <tr>
- <td>
- Age:
- </td>
- <td>
- <input type="text" th:field="*{age}" />
- </td>
- <td th:if="${#fields.hasErrors('age')}" th:errors="*{age}">
- Age Error
- </td>
- </tr>
- <tr>
- <td>
- <button type="submit">
- Submit
- </button>
- </td>
- </tr>
- </table>
- </form>
- </body>
- </HTML>
form.HTML 页面包含一个简单的 form 表格, 这个表格和 post 方法绑定. th:object 表示该表格和后端的 person 对象绑定, 这就是 bean-backed form, 在 PersonForm 对象中, 可以看到 th:field="*{name}" 和 th:field=*{age}. 在 form 表格中, 紧挨着 name 和 age 标签, 有两个用于显示错误信息的标签. 页面的最后有个 Submit 按钮, 如果用户输入的 name 和 age 不合法, 页面会显示错误提示信息, 如果用户输入的 name 和 age 不合法, 页面会被路由到下一个页面.
results.HTML 内容如下:
- <!DOCTYPE HTML>
- <HTML lang="zh-CN">
- <head>
- <meta charset="UTF-8" />
- <title>
- Title
- </title>
- </head>
- <body>
- Congratulations! You are old enough to sign up for this site.
- </body>
- </HTML>
创建程序启动类
创建一个 Application 类, 用于启动 Spring Boot 应用,
- package hello;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- /**
- * Created by IntelliJ IDEA.
- * User: duqi
- * Date: 2017/3/2
- * Time: 15:50
- */
- @SpringBootApplication
- public class Application {
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
- }
@SpringBootApplication 注解也为 Thymeleaf 提供了默认配置: 默认情况下会从 resources/templates 目录下查找模板文件, 并将 *.HTML 文件中的后缀忽略掉后剩下的文件名称解析为视图. 可以通过在 application.properties 里设置相关属性来修改 Thymeleaf 的配置, 这里我们不再细说.
演示的代码: https://github.com/duqicauc/validatingforminput
Spring Boot 1.x 系列
Spring Boot 的自动配置, Command-line-Runner http://www.javaadu.online/?p=487
了解 Spring Boot 的自动配置 http://www.javaadu.online/?p=495
Spring Boot 的 @PropertySource 注解在整合 Redis 中的使用 http://www.javaadu.online/?p=499
Spring Boot 项目中如何定制 HTTP 消息转换器 http://www.javaadu.online/?p=515
Spring Boot 整合 MongoDB 提供 Restful 接口 http://www.javaadu.online/?p=518
Spring 中 bean 的 scope http://www.javaadu.online/?p=521
Spring Boot 项目中使用事件派发器模式 http://www.javaadu.online/?p=526
Spring Boot 提供 RESTful 接口时的错误处理实践 http://www.javaadu.online/?p=530
Spring Boot 实战之定制自己的 starter http://www.javaadu.online/?p=535
Spring Boot 项目如何同时支持 HTTP 和 HTTPS 协议 http://www.javaadu.online/?p=538
自定义的 Spring Boot starter 如何设置自动配置注解 http://www.javaadu.online/?p=546
Spring Boot 项目中使用 Mockito http://www.javaadu.online/?p=575
在 Spring Boot 项目中使用 Spock 测试框架 http://www.javaadu.online/?p=588
Spring Boot 项目中如何定制拦截器 http://www.javaadu.online/?p=590
Spring Boot 项目中如何定制 PropertyEditors http://www.javaadu.online/?p=593
本号专注于后端技术, JVM 问题排查和优化, Java 面试题, 个人成长和自我管理等主题, 为读者提供一线开发者的工作和成长经验, 期待你能在这里有所收获.
来源: https://www.cnblogs.com/javaadu/p/11756248.html