知識庫 / Spring / Spring Boot RSS 訂閱

Spring Boot 基於 Thymeleaf 的 CRUD 應用

Spring Boot,Spring MVC
HongKong
11
01:36 PM · Dec 06 ,2025

1. 概述

提供對 JPA 實體的 CRUD 功能的 DAO 層實現可能是一項重複且耗時的任務,我們通常希望避免這種情況。

幸運的是,Spring Boot 使得通過 JPA 基礎的 CRUD 倉庫層創建 CRUD 應用程序變得容易。

在本教程中,我們將學習如何使用 Spring Boot 和 Thymeleaf 開發一個 CRUD Web 應用程序。

2. Maven 依賴項

在這種情況下,我們將依賴 spring-boot-starter-parent 用於簡單的依賴管理、版本控制和插件配置。

因此,我們不需要在我們的 pom.xml 文件中指定項目的依賴版本,除了覆蓋 Java 版本外:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</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>
    </dependency>
</dependencies>

3. 領域層

在所有項目依賴項已就位之後,讓我們現在實現一個簡單的領域層。

為了簡化起見,該層將包含一個單一的類,該類將負責建模 User 實體:

@Entity
public class User {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    
    @NotBlank(message = "Name is mandatory")
    private String name;
    
    @NotBlank(message = "Email is mandatory")
    private String email;

    // standard constructors / setters / getters / toString
}

請記住,我們已使用 @Entity 註解對該類進行了標註。因此,在 Hibernate(作為 JPA 實現)在這種情況下,能夠對領域實體執行 CRUD 操作。 有關 Hibernate 5 與 Spring 的入門指南,請訪問我們的教程。

此外,我們使用 @NotBlank 約束對 nameemail 字段進行了約束。這意味着我們可以使用 Hibernate 驗證器在將實體持久化或更新到數據庫之前驗證受約束字段。

有關此方面的基本知識,請查看我們相關的 Bean 驗證器教程。

4. 存儲層 (Repository Layer)

目前,我們的示例 Web 應用程序什麼也不做。但情況即將改變。

Spring Data JPA 允許我們使用最小的努力實現基於 JPA 的存儲庫 (JPA 模式實現的精巧名稱)。

Spring Data JPA 是 Spring Boot 的 spring-boot-starter-data-jpa 的關鍵組件,它使通過在 JPA 實現之上放置的強大抽象層添加 CRUD 功能變得容易。 這種抽象層允許我們訪問持久層,而無需從頭開始提供自己的 DAO 實現。

為了為我們的應用程序提供基本的 CRUD 功能,用於 User 對象,我們只需要擴展 CrudRepository 接口:

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

這就是全部!通過擴展 CrudRepository 接口,Spring Data JPA 將為該接口的 CRUD 方法提供實現。

5.&nbsp;控制器層

由於 spring-boot-starter-data-jpa 在底層 JPA 實現之上提供的抽象層,我們可以通過基本的 Web 層將 CRUD 功能輕鬆地添加到我們的 Web 應用程序中。

在我們的案例中,一個簡單的控制器類就足以處理 GET 和 POST HTTP 請求,並將它們映射到我們對 UserRepository 實現的調用。

控制器類依賴於 Spring MVC 的一些關鍵功能。有關 Spring MVC 的詳細指南,請查看我們的 Spring MVC 教程。

讓我們從控制器中 showSignUpForm()addUser() 方法開始。

前者將顯示用户註冊表單,而後者將在驗證約束字段後將新實體持久化到數據庫中。

如果實體未通過驗證,則註冊表單將重新顯示。

否則,一旦實體已保存,則持久化實體的列表將更新到相應的視圖中:

@Controller
public class UserController {
    
    @GetMapping("/signup")
    public String showSignUpForm(User user) {
        return "add-user";
    }
    
    @PostMapping("/adduser")
    public String addUser(@Valid User user, BindingResult result, Model model) {
        if (result.hasErrors()) {
            return "add-user";
        }
        
        userRepository.save(user);
        return "redirect:/index";
    }

    // additional CRUD methods
}

我們還需要一個對 /index URL 的映射。

@GetMapping("/index")
public String showUserList(Model model) {
    model.addAttribute("users", userRepository.findAll());
    return "index";
}

<em >UserController</em> 中,我們還將擁有 <em >showUpdateForm()</em> 方法,該方法負責從數據庫中檢索與提供的 <em >id</em> 匹配的 <em >User</em> 實體。

如果實體存在,它將被傳遞給更新表單視圖作為模型屬性。

因此,表單可以填充 <em >name</em><em >email</em> 字段的值。

@GetMapping("/edit/{id}")
public String showUpdateForm(@PathVariable("id") long id, Model model) {
    User user = userRepository.findById(id)
      .orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id));
    
    model.addAttribute("user", user);
    return "update-user";
}

最後,我們有 updateUser()deleteUser() 方法在 UserController 類中。

第一個方法將更新後的實體持久化到數據庫中,而最後一個方法將刪除指定的實體。

無論哪種情況,持久化實體的列表都會相應地更新:

@PostMapping("/update/{id}")
public String updateUser(@PathVariable("id") long id, @Valid User user, 
  BindingResult result, Model model) {
    if (result.hasErrors()) {
        user.setId(id);
        return "update-user";
    }
        
    userRepository.save(user);
    return "redirect:/index";
}
    
@GetMapping("/delete/{id}")
public String deleteUser(@PathVariable("id") long id, Model model) {
    User user = userRepository.findById(id)
      .orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id));
    userRepository.delete(user);
    return "redirect:/index";
}

6. 視圖層

到目前為止,我們已經實現了對 User實體執行CRUD操作的函數控制器類。 即便如此,此模式中仍然缺少一個關鍵組件:視圖層。

src/main/resources/templates文件夾中,我們需要創建用於顯示註冊表單和更新表單,以及呈現持久化 User實體的HTML模板。

正如在介紹中所述,我們將使用Thymeleaf作為底層模板引擎來解析模板文件。

以下是 add-user.html文件的相關部分:

<form action="#" th:action="@{/adduser}" th:object="${user}" method="post">
    <label for="name">Name</label>
    <input type="text" th:field="*{name}" id="name" placeholder="Name">
    <span th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span>
    <label for="email">Email</label>
    <input type="text" th:field="*{email}" id="email" placeholder="Email">
    <span th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></span>
    <input type="submit" value="Add User">   
</form>

請注意我們使用了 @{/adduser} URL 表達式來指定表單的 action 屬性,以及 ${} 變量表達式來在模板中嵌入動態內容,例如 nameemail 字段的值以及驗證後的錯誤信息。

類似於 add-user.html,以下是 update-user.html 模板的外觀:

<form action="#" 
  th:action="@{/update/{id}(id=${user.id})}" 
  th:object="${user}" 
  method="post">
    <label for="name">Name</label>
    <input type="text" th:field="*{name}" id="name" placeholder="Name">
    <span th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span>
    <label for="email">Email</label>
    <input type="text" th:field="*{email}" id="email" placeholder="Email">
    <span th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></span>
    <input type="submit" value="Update User">   
</form>

最後,我們有 index.html 文件,它顯示了持久化實體的列表,以及編輯和刪除現有實體的鏈接:

<div th:switch="${users}">
    <h2 th:case="null">No users yet!</h2>
        <div th:case="*">
            <h2>Users</h2>
            <table>
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Email</th>
                        <th>Edit</th>
                        <th>Delete</th>
                    </tr>
                </thead>
                <tbody>
                <tr th:each="user : ${users}">
                    <td th:text="${user.name}"></td>
                    <td th:text="${user.email}"></td>
                    <td><a th:href="@{/edit/{id}(id=${user.id})}">Edit</a></td>
                    <td><a th:href="@{/delete/{id}(id=${user.id})}">Delete</a></td>
                </tr>
            </tbody>
        </table>
    </div>      
    <p><a href="/signup">Add a new user</a></p>
</div>

為了簡化起見,這些模板看起來非常簡陋,只提供所需的功能,而沒有添加不必要的外觀效果

為了讓模板看起來更具吸引力,同時避免花費過多時間在 HTML/CSS 上,我們可以輕鬆地使用免費的 Twitter Bootstrap UI 套件,例如 Shards

7. 運行應用程序

最後,讓我們定義應用程序的入口點。

如大多數 Spring Boot 應用程序一樣,我們可以使用簡單的 main() 方法來完成:

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

現在,讓我們在我們的 IDE 中點擊“運行”,然後打開瀏覽器,將其指向 http://localhost:8080

如果構建已成功編譯,我們應該看到一個基本的 CRUD 用户儀表板,其中包含添加新實體和編輯、刪除現有實體的鏈接。

8. 結論

在本文中,我們學習瞭如何使用 Spring Boot 和 Thymeleaf 構建一個基本的 CRUD Web 應用程序。

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

發佈 評論

Some HTML is okay.