javascript
Thymeleaf + Spring中的验证
總覽
我們將要討論的重要主題涉及空值,空字符串和輸入驗證,因此我們不會在數據庫中輸入無效數據。
在處理空值時,我們使用了Java 1.8中引入的java.util.Optional 。
0 – Spring Boot + Thymeleaf示例表單驗證應用程序
我們正在為一所大學構建一個Web應用程序,使潛在的學生可以請求有關其課程的信息。
查看并從 Github 下載代碼
1 –項目結構
2 –項目依賴性
除了典型的Spring Boot依賴關系之外,我們還在 LEGACYHTML5模式下使用嵌入式HSQLDB數據庫和nekohtml 。
<?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.michaelcgood</groupId><artifactId>michaelcgood-validation-thymeleaf</artifactId><version>0.0.1</version><packaging>jar</packaging><name>michaelcgood-validation-thymeleaf</name><description>Michael C Good - Validation in Thymeleaf Example Application</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.7.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.hsqldb</groupId><artifactId>hsqldb</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- legacy html allow --><dependency><groupId>net.sourceforge.nekohtml</groupId><artifactId>nekohtml</artifactId><version>1.9.21</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>3 –模型
在我們的模型中,我們定義:
- 自動生成的ID字段
- 名稱字段不能為空
- 名稱必須在2到40個字符之間
- 由@Email批注驗證的電子郵件字段
- 布爾字段“開放日”,允許潛在學生指出她是否想參加開放日
- 布爾字段“訂閱”,用于訂閱電子郵件更新
- 注釋字段是可選的,因此沒有最低字符要求,但有最高字符要求
4 –儲存庫
我們定義一個存儲庫。
package com.michaelcgood.dao;import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository;import com.michaelcgood.model.Student;@Repository public interface StudentRepository extends JpaRepository<Student,Long> {}5 –控制器
我們注冊StringTrimmerEditor將空字符串自動轉換為空值。
當用戶發送POST請求時,我們希望接收該Student對象的值,因此我們使用@ModelAttribute來做到這一點。
為確保用戶發送的值有效,我們接下來使用適當命名的@Valid批注。
BindingResult必須緊隨其后,否則在提交無效數據而不是保留在表單頁面時, 將為用戶提供錯誤頁面。
我們使用if ... else來控制用戶提交表單時發生的情況。 如果用戶提交了無效數據,則該用戶將保留在當前頁面上,而在服務器端將不再發生任何事情。 否則,應用程序將使用用戶的數據,并且用戶可以繼續。
在這一點上,檢查學生的姓名是否為空是多余的,但是我們這樣做。 然后,我們調用下面定義的方法checkNullString ,以查看注釋字段是空的String還是null。
package com.michaelcgood.controller;import java.util.Optional;import javax.validation.Valid;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.propertyeditors.StringTrimmerEditor; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import com.michaelcgood.dao.StudentRepository; import com.michaelcgood.model.Student;@Controller public class StudentController {@InitBinderpublic void initBinder(WebDataBinder binder) {binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));}public String finalString = null;@Autowiredprivate StudentRepository studentRepository;@PostMapping(value="/")public String addAStudent(@ModelAttribute @Valid Student newStudent, BindingResult bindingResult, Model model){if (bindingResult.hasErrors()) {System.out.println("BINDING RESULT ERROR");return "index";} else {model.addAttribute("student", newStudent);if (newStudent.getName() != null) {try {// check for comments and if not present set to 'none'String comments = checkNullString(newStudent.getComments());if (comments != "None") {System.out.println("nothing changes");} else {newStudent.setComments(comments);}} catch (Exception e) {System.out.println(e);}studentRepository.save(newStudent);System.out.println("new student added: " + newStudent);}return "thanks";}}@GetMapping(value="thanks")public String thankYou(@ModelAttribute Student newStudent, Model model){model.addAttribute("student",newStudent);return "thanks";}@GetMapping(value="/")public String viewTheForm(Model model){Student newStudent = new Student();model.addAttribute("student",newStudent);return "index";}public String checkNullString(String str){String endString = null;if(str == null || str.isEmpty()){System.out.println("yes it is empty");str = null;Optional<String> opt = Optional.ofNullable(str);endString = opt.orElse("None");System.out.println("endString : " + endString);}else{; //do nothing}return endString;}}Optional.ofNullable(str); 表示字符串將成為數據類型Optional,但是字符串可以為空值。
endString = opt.orElse(“ None”); 如果變量opt為null,則將String值設置為“ None”。
6 – Thymeleaf模板
正如您在上面的Controller映射中所看到的,有兩個頁面。 index.html是我們的主頁,具有針對潛在大學生的表格。
我們的主要對象是學生,因此我們的th:object當然是指該對象 。 我們模型的字段分別進入th:field 。
我們將表單的輸入包裝在表格中以進行格式化。
在每個表單元格(td)下,我們都有一個條件語句,如下所示: […] th:if =” $ {#fields.hasErrors('name')}“ th:errors =” * {name}”
[…]
上面的條件語句意味著,如果用戶在該字段中輸入的數據與我們在Student模型中對該字段的要求不符,然后提交表單,則在用戶返回此頁面時顯示輸入要求。
index.html
<html xmlns="http://www.w3.org/1999/xhtml"xmlns:th="http://www.thymeleaf.org"><head> <!-- CSS INCLUDE --> <link rel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"crossorigin="anonymous"></link><!-- EOF CSS INCLUDE --> </head> <body><!-- START PAGE CONTAINER --><div class="container-fluid"><!-- PAGE TITLE --><div class="page-title"><h2><span class="fa fa-arrow-circle-o-left"></span> Request UniversityInfo</h2></div><!-- END PAGE TITLE --><div class="column"><form action="#" th:action="@{/}" th:object="${student}"method="post"><table><tr><td>Name:</td><td><input type="text" th:field="*{name}"></input></td><td th:if="${#fields.hasErrors('name')}" th:errors="*{name}">NameError</td></tr><tr><td>Email:</td><td><input type="text" th:field="*{email}"></input></td><td th:if="${#fields.hasErrors('email')}" th:errors="*{email}">EmailError</td></tr><tr><td>Comments:</td><td><input type="text" th:field="*{comments}"></input></td></tr><tr><td>Open House:</td><td><input type="checkbox" th:field="*{openhouse}"></input></td></tr><tr><td>Subscribe to updates:</td><td><input type="checkbox" th:field="*{subscribe}"></input></td></tr><tr><td><button type="submit" class="btn btn-primary">Submit</button></td></tr></table></form></div><!-- END PAGE CONTENT --><!-- END PAGE CONTAINER --></div><script src="https://code.jquery.com/jquery-1.11.1.min.js"integrity="sha256-VAvG3sHdS5LqTT+5A/aeq/bZGa/Uj04xKxY8KM/w9EE="crossorigin="anonymous"></script><scriptsrc="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"crossorigin="anonymous"></script></body> </html>這是用戶成功完成表單后看到的頁面。 我們使用th:text向用戶顯示他或她在該字段中輸入的文本。
Thanks.html
<html xmlns="http://www.w3.org/1999/xhtml"xmlns:th="http://www.thymeleaf.org"><head> <!-- CSS INCLUDE --> <link rel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"crossorigin="anonymous"></link><!-- EOF CSS INCLUDE --></head> <body><!-- START PAGE CONTAINER --><div class="container-fluid"><!-- PAGE TITLE --><div class="page-title"><h2><span class="fa fa-arrow-circle-o-left"></span> Thank you</h2></div><!-- END PAGE TITLE --><div class="column"><table class="table datatable"><thead><tr><th>Name</th><th>Email</th><th>Open House</th><th>Subscribe</th><th>Comments</th></tr></thead><tbody><tr th:each="student : ${student}"><td th:text="${student.name}">Text ...</td><td th:text="${student.email}">Text ...</td><td th:text="${student.openhouse}">Text ...</td><td th:text="${student.subscribe}">Text ...</td><td th:text="${student.comments}">Text ...</td></tr></tbody></table></div> </div><!-- END PAGE CONTAINER --></div><scriptsrc="https://code.jquery.com/jquery-1.11.1.min.js"integrity="sha256-VAvG3sHdS5LqTT+5A/aeq/bZGa/Uj04xKxY8KM/w9EE="crossorigin="anonymous"></script><scriptsrc="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"crossorigin="anonymous"></script></body> </html>7 –配置
使用Spring Boot Starter并包括Thymeleaf依賴項,您將自動擁有/ templates /的模板位置,并且Thymeleaf可以直接使用。 因此,不需要大多數這些設置。
要注意的一個設置是nekohtml提供的LEGACYHTM5 。 如果需要,這使我們可以使用更多隨意HTML5標簽。 否則,Thymeleaf將非常嚴格,并且可能無法解析您HTML。 例如,如果您不關閉輸入標簽,Thymeleaf將不會解析您HTML。
application.properties
#================================== # = Thymeleaf configurations #================================== spring.thymeleaf.check-template-location=true spring.thymeleaf.prefix=classpath:/templates/ spring.thymeleaf.suffix=.html spring.thymeleaf.content-type=text/html spring.thymeleaf.cache=false spring.thymeleaf.mode=LEGACYHTML5server.contextPath=/8 –演示
主頁
在這里,我們到達主頁。
無效數據
我在名稱字段和電子郵件字段中輸入了無效數據。
有效數據,無評論
現在,我在所有字段中輸入了有效數據,但未提供注釋。 不需要提供評論。 在我們的控制器中,我們使所有空字符串都為空值。 如果用戶未提供注釋,則將String值設置為“ None”。
9 –結論
包起來
該演示應用程序演示了如何以Thymeleaf形式驗證用戶輸入。
我認為,Spring和Thymeleaf與javax.validation.constraints一起可以很好地驗證用戶輸入。
源代碼在 Github上
筆記
Java 8的Optional出于某種演示目的而被強加到該應用程序中,我想指出的是,當使用@RequestParam時 ,如我的PagingAndSortingRepository教程中所示,它可以更有機地工作。
但是,如果您不使用Thymeleaf,則可以將我們不需要的字段設置為Optional 。 Vlad Mihalcea在這里討論了使用JPA和Hibernate映射Optional實體屬性的最佳方法 。
翻譯自: https://www.javacodegeeks.com/2017/10/validation-thymeleaf-spring.html
總結
以上是生活随笔為你收集整理的Thymeleaf + Spring中的验证的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华为新品发布会预告视频:最大的阻力给我们
- 下一篇: 考验你的眼力,苹果 iPhone 15