En esta lección nos centraremos en el uso práctico de Thymeleaf dentro de una aplicación Spring MVC. Crearemos páginas web dinámicas con Thymeleaf y aprenderemos a generar páginas HTML con datos provenientes de nuestro controlador. Prepárate, hoy habrá mucho código, un poco de magia y algo sobre cómo el servidor web hace sus "trucos" para convertir peticiones en páginas bonitas.
Conectar Thymeleaf en un proyecto Spring MVC
Para empezar a usar Thymeleaf, hay que añadir la dependencia correspondiente en nuestro proyecto. Supondremos que usas Maven. Si tu proyecto usa Gradle, añade la dependencia equivalente.
Añadir Thymeleaf en pom.xml
<dependencies>
<!-- Spring Boot Starter for Thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>3.1.0</version> <!-- Usa la versión actual -->
</dependency>
</dependencies>
Después Maven descargará todas las librerías necesarias y tu proyecto estará listo para trabajar con Thymeleaf.
Configuración de Thymeleaf
Spring Boot configura automáticamente Thymeleaf para trabajar con plantillas que deben colocarse en la carpeta resources/templates. Si creas un proyecto con Spring Framework sin Spring Boot, tendrás que escribir la configuración para procesar las plantillas por tu cuenta.
Para simplificar usamos Spring Boot, así que toda la configuración ya viene "out of the box".
Primera aplicación con Thymeleaf
Paso 1: Creemos el controlador
Empezamos creando un controlador. Por ejemplo, queremos mostrar una lista de estudiantes en una página web.
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Arrays;
import java.util.List;
@Controller
public class StudentController {
@GetMapping("/students")
public String getStudents(Model model) {
// Creamos la lista de estudiantes
List<String> students = Arrays.asList("Iván Ivanov", "María Petrova", "Aleksei Sidorov");
// Añadimos la lista al objeto Model
model.addAttribute("students", students);
// Devolvemos el nombre de la plantilla (students.html)
return "students";
}
}
Qué ocurre aquí:
- Creamos el endpoint
/students, que maneja solicitudes GET. - En el método se crea la lista de estudiantes y se pasa al objeto
Model. Este objeto permite pasar datos desde el controlador a la plantilla. - El método devuelve el nombre del archivo de plantilla (
students.html). Spring MVC busca automáticamente la plantilla en la carpetaresources/templates.
Paso 2: Creamos la plantilla students.html
Crea en la carpeta resources/templates el archivo students.html. Contendrá HTML con pequeños elementos de Thymeleaf.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Lista de estudiantes</title>
</head>
<body>
<h1>Lista de estudiantes</h1>
<ul>
<!-- Expresión de Thymeleaf para mostrar los datos -->
<li th:each="student : ${students}" th:text="${student}"></li>
</ul>
</body>
</html>
Explicación:
xmlns:th="http://www.thymeleaf.org"- declaración del namespace para Thymeleaf.th:each="student : ${students}"- bucle donde iteramos cada estudiante de la listastudents.th:text="${student}"- mostramos el estudiante actual en el HTML.
Paso 3: Ejecutar la aplicación
Arranca la aplicación Spring Boot. Ve en el navegador a http://localhost:8080/students. Verás la página generada dinámicamente con la lista de estudiantes.
Trabajar con datos dinámicos
Thymeleaf soporta muchas expresiones para trabajar con datos. Aquí tienes algunos ejemplos:
Expresiones de Thymeleaf
| Sintaxis | Descripción |
|---|---|
${} |
Expresión para acceder a variables del modelo (${student} para acceder al objeto estudiante) |
th:text |
Establece el texto de un elemento (<p> -> <p>Texto</p>) |
th:href |
Fija el atributo href de un enlace (<a> -> <a href="URL">) |
th:if, th:unless |
Condiciones para mostrar HTML (th:if="${isLoggedIn}") |
Plantilla con enlaces dinámicos
Ejemplo donde añadimos enlaces para cada estudiante:
<ul>
<li th:each="student, iterStat : ${students}">
<a th:href="@{'/students/' + ${iterStat.index}}" th:text="${student}"></a>
</li>
</ul>
Aquí iterStat.index se usa para añadir el índice del elemento en el enlace.
Práctica: crear interfaz para entidades
Ahora hagamos renderizado del lado del servidor para una entidad que añadimos antes en nuestra aplicación.
Paso 1: Creamos la entidad Book
package com.example.demo.model;
public class Book {
private String title;
private String author;
public Book(String title, String author) {
this.title = title;
this.author = author;
}
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
}
Paso 2: Controlador para libros
package com.example.demo.controller;
import com.example.demo.model.Book;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;
@Controller
public class BookController {
@GetMapping("/books")
public String getBooks(Model model) {
// Lista de libros
List<Book> books = List.of(
new Book("Guerra y paz", "León Tolstói"),
new Book("Crimen y castigo", "Fiódor Dostoyevski"),
new Book("El maestro y Margarita", "Mijaíl Bulgákov")
);
model.addAttribute("books", books);
return "books";
}
}
Paso 3: Plantilla para libros books.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Lista de libros</title>
</head>
<body>
<h1>Lista de libros</h1>
<table>
<tr>
<th>Título</th>
<th>Autor</th>
</tr>
<tr th:each="book : ${books}">
<td th:text="${book.title}"></td>
<td th:text="${book.author}"></td>
</tr>
</table>
</body>
</html>
Consejos y errores comunes
- Indica correctamente el nombre de la plantilla. Cuando devuelves una cadena desde el controlador, debe coincidir con el nombre del archivo en la carpeta
templates. Si falta el archivo, recibirás el errorTemplate not found. - Espacio de nombres de Thymeleaf. No olvides añadir
xmlns:th="http://www.thymeleaf.org"en el elemento raíz del HTML. Sin esto, las directivas de Thymeleaf no funcionarán. - Trabajo con colecciones. Si pasas una colección al modelo, asegúrate de que no sea
null. Si es null, te dará error al iterar sobre ella.
Ahora tienes todas las herramientas para crear páginas HTML generadas dinámicamente con Thymeleaf. Usa este conocimiento para mejorar tu aplicación! 🎉
GO TO FULL VERSION