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 約束對 name 和 email 字段進行了約束。這意味着我們可以使用 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. 控制器層
由於 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 屬性,以及 ${} 變量表達式來在模板中嵌入動態內容,例如 name 和 email 字段的值以及驗證後的錯誤信息。
類似於 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 應用程序。