Spring Boot構建的Web項目如何在服務端校驗表單輸入

  • 2019 年 10 月 29 日
  • 筆記

本文首發於個人網站:Spring Boot構建的Web項目如何在服務端校驗表單輸入

這個例子用於演示在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插件提供了很多方便的特性:

  1. 它將該項目中需要的各個Jar包收集起來,並打包成可直接運行的Jar包,以更方便得部署和傳輸;
  2. 它會搜索包含「public static void main()」方法的類,該類就是可運行Jar包的啟動類;
  3. 它提供了內在的支援,去匹配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系列

  1. Spring Boot的自動配置、Command-line-Runner
  2. 了解Spring Boot的自動配置
  3. Spring Boot的@PropertySource註解在整合Redis中的使用
  4. Spring Boot項目中如何訂製HTTP消息轉換器
  5. Spring Boot整合Mongodb提供Restful介面
  6. Spring中bean的scope
  7. Spring Boot項目中使用事件派發器模式
  8. Spring Boot提供RESTful介面時的錯誤處理實踐
  9. Spring Boot實戰之訂製自己的starter
  10. Spring Boot項目如何同時支援HTTP和HTTPS協議
  11. 自定義的Spring Boot starter如何設置自動配置註解
  12. Spring Boot項目中使用Mockito
  13. 在Spring Boot項目中使用Spock測試框架
  14. Spring Boot項目中如何訂製攔截器
  15. Spring Boot項目中如何訂製PropertyEditors

本號專註於後端技術、JVM問題排查和優化、Java面試題、個人成長和自我管理等主題,為讀者提供一線開發者的工作和成長經驗,期待你能在這裡有所收穫。
javaadu