Thymeleaf是一个基于 Java 的服务器端模板引擎,适用于 Web 和独立环境,能够处理 HTML、XML、JavaScript、CSS 甚至纯文本。它比JPS更强大,负责UI上的动态内容渲染。该引擎允许后端和前端开发人员在同一视图上并行工作。它可以直接访问java对象和spring bean并将它们与UI绑定。当我们创建任何 Web 应用程序时,它主要与 Spring MVC 一起使用。那么让我们从一个示例开始来了解 Thymeleaf 如何与 Spring 框架配合使用。
项目设置
这里我们将对Employee数据集进行增删改查操作。因此,为了构建它,我们必须添加某些依赖项,这些依赖项以项目符号形式列出或在 pom.xml 中列出。
- Spring Web(使用 Spring MVC 构建 Web,包括 RESTful 应用程序。使用 Apache Tomcat 作为默认嵌入式容器。)
- Spring Data JPA(使用 Spring Data 和 Hibernate 通过 Java Persistence API 将数据保存在 SQL 存储中。)
- Spring Boot Devtools(提供快速应用程序重启、LiveReload 和配置以增强开发体验)
- MySQL 驱动程序(MySQL JDBC 和 R2DBC 驱动程序)
- Thymeleaf(适用于 Web 和独立环境的服务器端 Java 模板引擎。允许 HTML 在浏览器中正确显示并作为静态原型。)
<?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 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>2.6.2</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>thymeleaf</artifactId> <version>0.0.1-SNAPSHOT</version> <name>thymeleaf</name> <description>Demo project for Spring Boot</description> <properties> <java.version>17</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.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</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.properties 文件
spring.jpa.hibernate.ddl-auto=update spring.datasource.url=jdbc:mysql://localhost:3306/emp spring.datasource.username=root spring.datasource.password=root spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect logging.level.org.hibernate.SQL=DEBUG logging.level.org.hibernate.type=TRACE
|
Employee Pojo
这是一个简单的 pojo 类,用于存储雇员的数据。
package com.microservice.modal;
import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id;
@Entity public class Employee { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private long id; private String name; private String email; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
|
Employee Service 接口和EmployeeServiceImpl 实现
package com.microservice.service;
import java.util.List;
import com.microservice.modal.Employee;
public interface EmployeeServices { List<Employee> getAllEmployee(); void save(Employee employee); Employee getById(Long id); void deleteViaId(long id); }
package com.microservice.service;
import com.microservice.modal.Employee; import com.microservice.repository.EmployeeRepository; import java.util.List; import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;
@Service public class EmployeeServiceImpl implements EmployeeServices {
@Autowired private EmployeeRepository empRepo;
@Override public List<Employee> getAllEmployee() { return empRepo.findAll(); }
@Override public void save(Employee employee) { empRepo.save(employee); }
@Override public Employee getById(Long id) { Optional<Employee> optional = empRepo.findById(id); Employee employee = null; if (optional.isPresent()) employee = optional.get(); else throw new RuntimeException( "Employee not found for id : " + id); return employee; }
@Override public void deleteViaId(long id) { empRepo.deleteById(id); } }
|
EmployeeRepository 接口:
package com.microservice.repository;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository;
import com.microservice.modal.Employee;
@Repository public interface EmployeeRepository extends JpaRepository<Employee,Long> {
}
EmployeeController 类
package com.microservice.controller;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping;
import com.microservice.modal.Employee; import com.microservice.service.EmployeeServiceImpl;
@Controller public class EmployeeController {
@Autowired private EmployeeServiceImpl employeeServiceImpl;
@GetMapping("/") public String viewHomePage(Model model) { model.addAttribute("allemplist", employeeServiceImpl.getAllEmployee()); return "index"; }
@GetMapping("/addnew") public String addNewEmployee(Model model) { Employee employee = new Employee(); model.addAttribute("employee", employee); return "newemployee"; }
@PostMapping("/save") public String saveEmployee(@ModelAttribute("employee") Employee employee) { employeeServiceImpl.save(employee); return "redirect:/"; }
@GetMapping("/showFormForUpdate/{id}") public String updateForm(@PathVariable(value = "id") long id, Model model) { Employee employee = employeeServiceImpl.getById(id); model.addAttribute("employee", employee); return "update"; }
@GetMapping("/deleteEmployee/{id}") public String deleteThroughId(@PathVariable(value = "id") long id) { employeeServiceImpl.deleteViaId(id); return "redirect:/";
} }
|
- 这是控制器类,主要控制数据流。它控制数据流进入模型对象,并在数据发生变化时更新视图。在这里,我们使用 Thymeleaf 映射对象数据。
- 当用户在浏览器上输入 URL localhost:8080/ 时,请求将转到 viewHomePage() 方法,在该方法中,我们将获取雇员列表,并将其添加到带有键、值对的模态中,然后返回 index.html 页面。在 index.html 页面中,键(allemplist)被识别为一个 java 对象,Thymeleaf 会遍历该列表,并根据用户提供的模板生成动态内容。
- /addNew - 当用户点击添加员工按钮时,请求将转到 addNewEmployee() 方法。在该方法中,我们只需创建雇员的空对象,并将其发送回 newemployee.html,这样用户就可以在这个空对象中填写数据。当用户点击保存按钮时,/save 映射就会运行,并获取雇员的对象并将该对象保存到数据库中。
- /showFormForUpdate/{id} - 该映射用于更新现有雇员数据。
- /deleteEmployee/{id} - 该映射用于删除现有雇员数据。
index.html
该页面用于显示员工列表。在这里,我们对控制器通过 viewHomePage() 方法发送的 allemplist 对象进行迭代。
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="ISO-8859-1"> <title>Employee</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> </head> <body> <div class="container my-2" align="center">
<h3>Employee List</h3> <a th:href="@{/addnew}" class="btn btn-primary btn-sm mb-3" >Add Employee</a> <table style="width:80%" border="1" class = "table table-striped table-responsive-md"> <thead> <tr> <th>Name</th> <th>Email</th> <th>Action</th> </tr> </thead> <tbody> <tr th:each="employee:${allemplist}"> <td th:text="${employee.name}"></td> <td th:text="${employee.email}"></td> <td> <a th:href="@{/showFormForUpdate/{id}(id=${employee.id})}" class="btn btn-primary">Update</a> <a th:href="@{/deleteEmployee/{id}(id=${employee.id})}" class="btn btn-danger">Delete</a> </td> </tr> </tbody> </table> </div> </body> </html>
|
newemployee.html
该页面用于在数据库中添加新员工。在这里,我们只需在空白字段中提供值,然后点击提交按钮。然后,雇员的数据将进入 saveEmployee() 方法,并保存到数据库中。
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="ISO-8859-1"> <title>Employee Management System</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> </head> <body> <div class="container"> <h1>Employee Management System</h1> <hr> <h2>Save Employee</h2>
<form action="#" th:action="@{/save}" th:object="${employee}" method="POST"> <input type="text" th:field="*{name}" placeholder="Employee Name" class="form-control mb-4 col-4"> <input type="text" th:field="*{email}" placeholder="Employee Email" class="form-control mb-4 col-4">
<button type="submit" class="btn btn-info col-2">Save Employee</button> </form>
<hr>
<a th:href="@{/}"> Back to Employee List</a> </div> </body> </html>
|
update.html
该页面用于更新现有雇员的数据。
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="ISO-8859-1"> <title>Employee Management System</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"> </head> <body> <div class="container"> <h1>Employee Management System</h1> <hr> <h2>Update Employee</h2>
<form action="#" th:action="@{/save}" th:object="${employee}" method="POST"> <!-- Add hidden form field to handle update --> <input type="hidden" th:field="*{id}" /> <input type="text" th:field="*{Name}" class="form-control mb-4 col-4"> <input type="text" th:field="*{email}" class="form-control mb-4 col-4"> <button type="submit" class="btn btn-info col-2"> Update Employee</button> </form> <hr> <a th:href = "@{/}"> Back to Employee List</a> </div> </body> </html>
|