知識庫 / Spring / Spring MVC RSS 訂閱

Thymeleaf 中顯示錯誤消息

Spring MVC
HongKong
8
12:33 PM · Dec 06 ,2025

1. 概述

本教程將演示如何在 Thymeleaf 模板中顯示來自 Spring 驅動的後端應用程序中的錯誤消息。

為了演示目的,我們將創建一個簡單的 Spring Boot 用户註冊應用程序,並驗證每個輸入字段。此外,我們還將演示如何處理全局級別錯誤。

首先,我們將快速設置後端應用程序,然後轉向 UI 部分。

2. 示例 Spring Boot 應用

為了創建一個簡單的 Spring Boot 應用用於用户註冊,我們需要一個控制器、一個倉庫和一個實體

然而,在此之前,我們應該添加 Maven 依賴項。

2.1. Maven 依賴

讓我們添加我們需要的全部 Spring Boot Starter – Web 用於 MVC 功能,Validation 用於 Hibernate 實體驗證,Thymeleaf 用於 UI,以及 JPA 用於倉庫。 此外,我們還需要一個 H2 依賴,以便使用內存數據庫:

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-web</artifactId> 
</dependency> 
<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-validation</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-data-jpa</artifactId> 
</dependency> 
<dependency> 
    <groupId>com.h2database</groupId> 
    <artifactId>h2</artifactId> 
    <scope>runtime</scope> 
    <version>1.4.200</version> 
</dependency>

2.2. 實體

以下是 用户 實體:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @NotEmpty(message = "User's name cannot be empty.")
    @Size(min = 5, max = 250)
    private String fullName;

    @NotEmpty(message = "User's email cannot be empty.")
    private String email;

    @NotNull(message = "User's age cannot be null.")
    @Min(value = 18)
    private Integer age;

    private String country;

    private String phoneNumber;

    // getters and setters
}

如我們所見,我們添加了多種用户輸入驗證約束。例如,字段不應為 null 或為空,並且應具有特定的大小或值。

值得注意的是,我們沒有為 國家電話號碼 字段添加任何約束。這是因為我們將使用它們作為生成全局錯誤或與特定字段無關的錯誤的示例。

2.3. 存儲庫

我們將使用一個簡單的 JPA 存儲庫來滿足我們的基本用例:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {}

2.4. 控制器

最後,為了在後端將所有內容連接起來,我們創建一個 UserController

@Controller
public class UserController {

    @Autowired
    private UserRepository repository;
    @GetMapping("/add")
    public String showAddUserForm(User user) {
        return "errors/addUser";
    }

    @PostMapping("/add")
    public String addUser(@Valid User user, BindingResult result, Model model) {
        if (result.hasErrors()) {
            return "errors/addUser";
        }
        repository.save(user);
        model.addAttribute("users", repository.findAll());
        return "errors/home";
    }
}

在這裏,我們定義了一個 GetMapping 在路徑 /add 上,用於顯示註冊表單。 我們的 PostMapping 在同一路徑上處理表單提交時的驗證,並在一切順利的情況下將其保存到存儲庫。

3. 使用 Thymeleaf 模板及錯誤消息

現在我們已經掌握了基本知識,接下來我們將探討關鍵部分,即創建 UI 模板並顯示錯誤消息(如果存在)。

讓我們逐步構建模板,根據我們能夠顯示的錯誤類型進行構建。

3.1. 顯示字段錯誤

Thymeleaf 提供了一個內置的 <em th:attrappend="hasErrors">field.hasErrors</em> 方法,它會根據給定字段是否存在錯誤返回一個布爾值。 結合使用它和 <em th:if="..."></em>,我們可以選擇在存在錯誤時顯示錯誤信息:

<p th:if="${#fields.hasErrors('age')}">Invalid Age</p>

接下來,如果我們想要添加任何樣式,可以使用 th:class 在條件語句中實現:

<p  th:if="${#fields.hasErrors('age')}" th:class="${#fields.hasErrors('age')}? error">
  Invalid Age</p>

我們的簡單嵌入式 CSS 類 error 會將元素設置為紅色:

<style>
    .error {
        color: red;
    }
</style>

另一個 Thymeleaf 屬性 賦予我們以指定選擇器顯示所有錯誤的權限,例如

<div>
    <label for="email">Email</label> <input type="text" th:field="*{email}" />
    <p th:if="${#fields.hasErrors('email')}" th:errorclass="error" th:errors="*{email}" />
</div>

在上面的片段中,我們還可以看到在 CSS 樣式使用上的變化。這裏我們使用 <em th:errorclass</em>,這消除了我們使用任何條件屬性來應用 CSS 的需求。

或者,我們也可以選擇使用 <em th:each</em> 遍歷給定字段上的所有驗證消息:

<div>
    <label for="fullName">Name</label> <input type="text" th:field="*{fullName}" 
      id="fullName" placeholder="Full Name">
    <ul>
        <li th:each="err : ${#fields.errors('fullName')}" th:text="${err}" class="error" />
    </ul>
</div>

特別地,我們在這裏使用了另一個 Thymeleaf 方法 fields.errors(),用於收集後端應用程序返回的關於 fullName 字段的所有驗證消息。

為了測試這一點,讓我們啓動我們的 Boot 應用並訪問端點 http://localhost:8080/add

這是當我們沒有提供任何輸入時頁面的外觀:

3.2. 同時顯示所有錯誤

接下來,讓我們看看如何避免逐個顯示每個錯誤消息,而是將它們全部在一個地方顯示。

為此,我們將使用 Thymeleaf 的 <em >fields.hasAnyErrors()</em> 方法。

<div th:if="${#fields.hasAnyErrors()}">
    <ul>
        <li th:each="err : ${#fields.allErrors()}" th:text="${err}" />
    </ul>
</div>

如我們所見,我們這裏使用了另一個變體 fields.allErrors() 來遍歷 HTML 表單上所有字段上的所有錯誤。

與其使用 fields.hasAnyErrors(),我們也可以使用 #fields.hasErrors('*')。同樣,#fields.errors('*') 是上面使用的 #fields.allErrors() 的另一種替代方案。

其效果如下:

3.3. 在表單外部顯示錯誤

接下來,讓我們考慮一個場景,即我們想要在 HTML 表單外部顯示驗證消息的情況。

在這種情況下,而不是使用選擇或 (*{….}), 我們只需要使用完全限定的變量名稱,格式為 (${….})

<h4>Errors on a single field:</h4>
<div th:if="${#fields.hasErrors('${user.email}')}"
 th:errors="*{user.email}"></div>
<ul>
    <li th:each="err : ${#fields.errors('user.*')}" th:text="${err}" />
</ul>

這將顯示所有錯誤消息,位於 電子郵件 字段中。

現在,讓我們看看如何一次性顯示所有消息

<h4>All errors:</h4>
<ul>
<li th:each="err : ${#fields.errors('user.*')}" th:text="${err}" />
</ul>

以下是我們看到的頁面內容:

3.4. 顯示全局錯誤

在實際場景中,可能存在與特定字段無關的錯誤。我們可能會遇到需要考慮多個輸入以驗證業務條件的用例。這些被稱為全局錯誤。

讓我們考慮一個簡單的例子來演示這一點。對於我們的國家電話號碼字段,我們可能會添加一個檢查,即對於給定的國家,電話號碼應以特定的前綴開頭。

我們需要在後端進行一些更改以添加此驗證。

首先,我們將添加一個服務來執行此驗證:

@Service
public class UserValidationService {
    public String validateUser(User user) {
        String message = "";
        if (user.getCountry() != null && user.getPhoneNumber() != null) {
            if (user.getCountry().equalsIgnoreCase("India") 
              && !user.getPhoneNumber().startsWith("91")) {
                message = "Phone number is invalid for " + user.getCountry();
            }
        }
        return message;
    }
}

如我們所見,我們添加了一個簡單的示例。對於國家 印度,電話號碼應以前綴 91 開頭。

其次,我們需要對控制器的 PostMapping 進行調整:

@PostMapping("/add")
public String addUser(@Valid User user, BindingResult result, Model model) {
    String err = validationService.validateUser(user);
    if (!err.isEmpty()) {
        ObjectError error = new ObjectError("globalError", err);
        result.addError(error);
    }
    if (result.hasErrors()) {
        return "errors/addUser";
    }
    repository.save(user);
    model.addAttribute("users", repository.findAll());
    return "errors/home";
}

最後,在 Thymeleaf 模板中,我們將添加常量 global 以顯示此類錯誤:

<div th:if="${#fields.hasErrors('global')}">
    <h3>Global errors:</h3>
    <p th:each="err : ${#fields.errors('global')}" th:text="${err}" class="error" />
</div>

或者,我們可以使用方法 #fields.hasGlobalErrors() 和 #fields.globalErrors() 代替常量,從而達到相同的效果。

以下是在輸入無效數據時看到的界面:

4. 結論

在本教程中,我們構建了一個 簡單的 Spring Boot 應用程序,用於演示如何使用 Thymeleaf 在各種類型的錯誤中顯示錯誤

我們探討了逐個顯示字段錯誤以及一次性顯示所有錯誤,以及超出 HTML 表單的全局錯誤。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.