Thymeleaf es un motor de plantillas basado en Java del lado del servidor para entornos web e independientes, capaz de procesar HTML, XML, JavaScript, CSS e incluso texto sin formato. Es más potente que JPS y responsable de la representación de contenido dinámico en la interfaz de usuario. El motor permite un trabajo paralelo de los desarrolladores de backend y frontend en la misma vista. Puede acceder directamente al objeto Java y Spring Beans y vincularlos con la interfaz de usuario. Y se usa principalmente con Spring MVC cuando creamos cualquier aplicación web. Entonces, comencemos con un ejemplo para comprender cómo funciona Thymeleaf con el marco Spring.
Configuración del proyecto
Aquí vamos a realizar una operación cruda en el conjunto de datos del empleado. Entonces, para construir esto, debemos agregar ciertas dependencias que se enumeran en forma de viñetas o también en pom.xml.
- Spring Web (Cree aplicaciones web, incluidas RESTful, utilizando Spring MVC. Utiliza Apache Tomcat como contenedor incrustado predeterminado).
- Spring Data JPA (persistencia de datos en almacenes SQL con la API de persistencia de Java usando Spring Data e Hibernate).
- Spring Boot Devtools (Proporciona reinicios rápidos de aplicaciones, LiveReload y configuraciones para una experiencia de desarrollo mejorada)
- Controlador MySQL (controlador MySQL JDBC y R2DBC)
- Thymeleaf (motor de plantillas Java del lado del servidor para entornos web e independientes. Permite que HTML se muestre correctamente en navegadores y como prototipos estáticos).
POM.XML
XML
<?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>
archivo 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
Empleado Pojo
Esta es la clase pojo simple que se usa para almacenar los datos de Employee.
Java
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; } }
Interfaz de Employee Service y clase EmployeeServiceImpl
Java
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); }
Clase EmployeeServiceImpl que implementa los métodos de interfaz de EmployeeService
Java
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); } }
Interfaz de repositorio de empleados
Aquí estamos usando JPA para comunicarnos y guardar el objeto en la base de datos.
Java
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> { }
Clase EmployeeController
Esta es la clase de controlador que básicamente controla el flujo de datos. Controla el flujo de datos en el objeto modelo y actualiza la vista cada vez que cambian los datos. Así que aquí estamos mapeando nuestros datos de objetos con Thymeleaf.
- Cuando el usuario escribe la URL localhost:8080/ en el navegador, la solicitud va al método viewHomePage() y en este método buscamos la lista de empleados y la agregamos al modal con clave, par de valores y devolvemos la página index.html . En la página index.html, la clave (allemplist) se identifica como un objeto java y Thymeleaf itera sobre la lista y genera contenido dinámico según la plantilla proporcionada por el usuario.
- /addNew: cuando el usuario hace clic en el botón Agregar empleado , la solicitud va al método addNewEmployee() . Y en este método, simplemente creamos el objeto vacío del empleado y lo enviamos de regreso a newemployee.html para que el usuario pueda completar los datos en este objeto vacío y cuando el usuario presiona el botón Guardar, se ejecuta el mapeo /guardar y obtener el objeto del empleado y guarde ese objeto en la base de datos.
- /showFormForUpdate/{id}: esta asignación es para actualizar los datos de empleados existentes.
- /deleteEmployee/{id}: esta asignación es para eliminar los datos de empleados existentes.
Java
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:/"; } }
índice.html
Esta página se utiliza para mostrar la lista de empleados. Aquí estamos iterando sobre el objeto allemplist que envía nuestro controlador desde el método viewHomePage() .
HTML
<!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>
nuevoempleado.html
Esta página se utiliza para agregar nuevos empleados en la base de datos. Aquí simplemente proporcionamos el valor en campos vacíos y hacemos clic en el botón Enviar. Luego, los datos del empleado van al método saveEmployee() y guardan los datos en la base de datos.
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" 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>
actualizar.html
Esta página se utiliza para actualizar los datos del empleado existente.
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>
Producción:
Publicación traducida automáticamente
Artículo escrito por shubhamp338 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA