表單驗證這樣處理才優(yōu)雅!深入掌握 Spring Boot 3.3 中的 MessageCodesResolver 錯誤處理技巧
在 Web 應(yīng)用開發(fā)中,表單驗證是確保數(shù)據(jù)正確性和安全性的重要步驟。當(dāng)用戶提交表單時,服務(wù)器端驗證可以防止惡意輸入、缺失數(shù)據(jù)或格式錯誤。而在 Spring Boot 中,表單驗證機(jī)制已經(jīng)非常成熟,特別是通過注解驅(qū)動的驗證方法,例如 @Valid 和 @NotBlank 等,能夠方便地驗證用戶提交的數(shù)據(jù)。
然而,僅僅依靠默認(rèn)的驗證機(jī)制,可能不足以提供豐富的用戶體驗,特別是在處理多層次、多語言支持的錯誤提示時。這里就需要引入 MessageCodesResolver,這是 Spring 提供的一種用于生成驗證錯誤碼的接口。它允許我們通過靈活的錯誤碼映射來為不同的字段生成不同層次的錯誤信息,從而實現(xiàn)多級驗證提示。使用 MessageCodesResolver,可以根據(jù)不同字段和錯誤類型生成不同的錯誤碼,支持更細(xì)粒度的錯誤反饋和國際化的處理。
運(yùn)行效果:
圖片
圖片
若想獲取項目完整代碼以及其他文章的項目源碼,且在代碼編寫時遇到問題需要咨詢交流,歡迎加入下方的知識星球。
本篇文章將詳細(xì)介紹如何使用 MessageCodesResolver,并結(jié)合 Spring Boot 3.3 中的其他驗證機(jī)制,構(gòu)建優(yōu)雅且靈活的表單驗證錯誤處理方案。
環(huán)境準(zhǔn)備
首先,確保我們有一個 Spring Boot 項目,并添加了必要的依賴,如 spring-boot-starter-web、spring-boot-starter-validation、spring-boot-starter-thymeleaf 以及 lombok。
項目依賴(pom.xml 配置)
<?xml versinotallow="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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.icoderoad</groupId>
<artifactId>spring-boot-messagecodes</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-messagecodes</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot Web Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置文件(application.yml)
server:
port: 8080
spring:
thymeleaf:
cache: false
messages:
basename: messages
MessageCodesResolver 概述
MessageCodesResolver 是 Spring 提供的一個非常靈活的接口,專門用于為驗證錯誤生成消息代碼。它的核心功能是根據(jù)字段名、對象名和驗證錯誤類型生成多個候選的錯誤消息碼,開發(fā)者可以為不同的字段和驗證類型配置特定的錯誤消息。
在默認(rèn)情況下,Spring 的驗證框架會為每個字段生成多條錯誤信息碼,這些碼會按優(yōu)先級依次匹配配置的消息文件。例如,假設(shè)你在表單中有一個 email 字段未通過 @NotBlank 驗證,那么默認(rèn)生成的錯誤碼可能包括:
- userForm.email.notblank
- email.notblank
- notblank
這三個不同層次的錯誤碼分別表示字段級別、全局級別和驗證類型級別的錯誤信息。通過 MessageCodesResolver,我們可以靈活地控制這些錯誤碼的生成方式,使得錯誤提示更加具有針對性。例如,在國際化(i18n)應(yīng)用中,不同語言可以針對不同的錯誤碼配置特定的消息提示。
通過自定義 MessageCodesResolver,我們可以精確地控制錯誤碼生成的規(guī)則,提供更優(yōu)雅的驗證反饋方案。
代碼實現(xiàn)
實體類定義
我們使用 Lombok 來簡化實體類的編寫,通過 @ConfigurationProperties 讀取表單配置屬性。
package com.icoderoad.messagecodes.entity;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "user")
public class UserForm {
@NotBlank(message = "{user.name.notblank}")
private String name;
@NotBlank(message = "{user.email.notblank}")
private String email;
}
控制器實現(xiàn)
在 Spring Boot 中,表單驗證通常通過 @Valid 注解和 BindingResult 一起使用。@Valid 注解用于觸發(fā)對綁定對象(例如表單對象)的驗證,而 BindingResult 則用于捕獲驗證結(jié)果。
@Valid 注解
@Valid 是 Java Bean Validation 中常用的注解,標(biāo)記在控制器的方法參數(shù)上時,Spring 框架會自動執(zhí)行驗證。它結(jié)合 JSR-303 和 Hibernate Validator 可以為實體字段進(jìn)行注解式的驗證。比如在我們的 UserForm 中,字段 name 和 email 分別使用了 @NotBlank 注解,當(dāng)提交的表單中這些字段為空時,@Valid 會捕獲并生成相應(yīng)的驗證錯誤。
BindingResult 詳解
BindingResult 是 Spring 中用于存儲驗證結(jié)果的對象,它包含了所有驗證失敗的字段和對應(yīng)的錯誤信息。通常情況下,BindingResult 作為 @Valid 參數(shù)的后一個參數(shù),用來判斷表單提交的數(shù)據(jù)是否存在錯誤。在控制器中,我們通過 BindingResult 來檢查是否有驗證錯誤,如果有,則可以返回相應(yīng)的錯誤提示。
package com.icoderoad.messagecodes.controller;
import com.icoderoad.messagecodes.entity.UserForm;
import jakarta.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class UserController {
@GetMapping("/")
public String showForm(UserForm userForm) {
return "index";
}
@PostMapping("/submit")
public String submitForm(@Valid UserForm userForm, BindingResult result, Model model) {
// 使用 BindingResult 檢查是否有驗證錯誤
if (result.hasErrors()) {
model.addAttribute("errors", result.getAllErrors());
return "index";
}
// 如果沒有錯誤,返回成功頁面
return "success";
}
}
自定義 MessageCodesResolver
接下來,我們將自定義一個 MessageCodesResolver 來生成多級錯誤碼,使錯誤消息更靈活。
package com.icoderoad.messagecodes.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.DefaultMessageCodesResolver;
import org.springframework.validation.MessageCodesResolver;
@Configuration
public class ValidationConfig {
@Bean
public MessageCodesResolver messageCodesResolver() {
DefaultMessageCodesResolver resolver = new DefaultMessageCodesResolver();
resolver.setMessageCodeFormatter(DefaultMessageCodesResolver.Format.POSTFIX_ERROR_CODE);
return resolver;
}
}
Thymeleaf 模板前端代碼
表單頁面通過 Thymeleaf 模板引擎渲染,并使用 jQuery 和 Bootstrap 實現(xiàn)前端樣式和表單驗證。
在 src/main/resources/templates 目錄下創(chuàng)建 index.html 文件:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>表單驗證</title>
<link rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h2>用戶注冊表單</h2>
<form action="#" th:action="@{/submit}" th:object="${userForm}" method="post">
<div class="form-group">
<label for="name">姓名</label>
<input type="text" class="form-control" th:field="*{name}" placeholder="請輸入姓名">
<small th:if="${#fields.hasErrors('name')}" th:errors="*{name}" class="form-text text-danger"></small>
</div>
<div class="form-group">
<label for="email">郵箱</label>
<input type="email" class="form-control" th:field="*{email}" placeholder="請輸入郵箱">
<small th:if="${#fields.hasErrors('email')}" th:errors="*{email}" class="form-text text-danger"></small>
</div>
<button type="submit" class="btn btn-primary">提交</button>
</form>
<div th:if="${errors != null}">
<ul class="text-danger">
<li th:each="error : ${errors}" th:text="${error.defaultMessage}"></li>
</ul>
</div>
</div>
</body>
</html>
創(chuàng)建 success.html
首先,在 src/main/resources/templates/ 目錄下創(chuàng)建一個名為 success.html 的文件。其內(nèi)容可以如下:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>表單提交成功</title>
<link rel="stylesheet">
</head>
<body>
<div class="container">
<h2>表單提交成功</h2>
<p>恭喜!表單已成功提交。</p>
<p>姓名:<span th:text="${user.name}"></span></p>
<p>郵箱:<span th:text="${user.email}"></span></p>
<a href="/" class="btn btn-primary">返回首頁</a>
</div>
</body>
</html>
國際化錯誤消息配置
在 src/main/resources 目錄下,創(chuàng)建 messages.properties 文件,存放國際化錯誤消息。
user.name.notblank=姓名不能為空
user.email.notblank=郵箱不能為空
運(yùn)行效果
運(yùn)行項目后,訪問 http://localhost:8080/,將看到一個用戶注冊表單。提交表單時,如果未填寫姓名或郵箱,系統(tǒng)會顯示對應(yīng)的錯誤信息。錯誤信息是通過 MessageCodesResolver 生成的多層次錯誤碼,并根據(jù)配置文件中的 messages.properties 中的消息碼映射到具體的提示文本。
我們在前端的 Thymeleaf 模板中使用 th:errors 來顯示錯誤信息,并通過 #fields.hasErrors() 方法來判斷表單字段是否存在錯誤。整個表單驗證過程非常流暢,并且錯誤提示靈活且易于維護(hù)。
總結(jié)
在這篇文章中,我們詳細(xì)講解了如何通過 Spring Boot 3.3 中的 MessageCodesResolver 實現(xiàn)更加優(yōu)雅的表單驗證錯誤處理。通過自定義 MessageCodesResolver,我們能夠為每個字段生成多級別的錯誤碼,使得驗證錯誤的處理更加靈活。在國際化場景下,開發(fā)者可以輕松為不同的語言配置不同的錯誤消息,提升用戶體驗。
通過結(jié)合 @Valid 注解和 BindingResult 對驗證結(jié)果的捕獲與處理,開發(fā)者可以輕松地實現(xiàn)后端數(shù)據(jù)驗證。同時,通過 Thymeleaf 渲染前端模板,配合 jQuery 和 Bootstrap,我們能夠構(gòu)建出用戶體驗良好的表單驗證機(jī)制。
在實際開發(fā)中,合理的表單驗證不僅能夠提升用戶體驗,還能有效防止惡意數(shù)據(jù)輸入,為應(yīng)用的安全性和穩(wěn)定性提供保障。