В этой лекции мы уделим внимание практическому применению Thymeleaf в приложении Spring MVC. Мы создадим динамические веб-страницы с помощью Thymeleaf, а также научимся генерировать HTML-страницы с данными, полученными из нашего контроллера. Готовьтесь, сегодня будет много кода, чуток магии и кое-что о том, как веб-сервер занимается "фокусами" по преобразованию запросов в красивые странички.
Подключение Thymeleaf в Spring MVC проект
Чтобы начать использовать Thymeleaf, нужно добавить соответствующую зависимость в наш проект. Мы предполагаем, что вы используете Maven. Если ваш проект на Gradle, добавьте аналогичную зависимость.
Добавление Thymeleaf в 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> <!-- Используйте актуальную версию -->
</dependency>
</dependencies>
После этого Maven скачает все необходимые библиотеки, и ваш проект будет готов к работе с Thymeleaf.
Настройка Thymeleaf
Spring Boot автоматически настраивает Thymeleaf для работы с шаблонами, которые нужно разместить в папке resources/templates. Если вы создаете проект на Spring Framework без Spring Boot, потребуется самостоятельно прописать конфигурацию для обработки шаблонов.
Для упрощения мы используем Spring Boot, поэтому вся настройка уже готова "из коробки".
Первое приложение с Thymeleaf
Шаг 1: Создадим контроллер
Начнем с создания контроллера. Например, мы хотим вывести список студентов на веб-странице.
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) {
// Создаем список студентов
List<String> students = Arrays.asList("Иван Иванов", "Мария Петрова", "Алексей Сидоров");
// Добавляем список в модель
model.addAttribute("students", students);
// Возвращаем имя шаблона (students.html)
return "students";
}
}
Что тут происходит:
- Мы создадим эндпоинт
/students, который обрабатывает GET-запросы. - В методе создается список студентов и передается в объект
Model. Этот объект позволяет передавать данные из контроллера в шаблон. - Метод возвращает имя файла шаблона (
students.html). Spring MVC автоматом ищет шаблон в папкеresources/templates.
Шаг 2: Создадим шаблон students.html
Создайте в папке resources/templates файл students.html. В нем будет HTML с небольшими элементами Thymeleaf.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Список студентов</title>
</head>
<body>
<h1>Список студентов</h1>
<ul>
<!-- Thymeleaf выражение для отображения данных -->
<li th:each="student : ${students}" th:text="${student}"></li>
</ul>
</body>
</html>
Объяснение:
xmlns:th="http://www.thymeleaf.org"- декларация пространства имен для Thymeleaf.th:each="student : ${students}"- цикл, в котором мы перебираем каждого студента из спискаstudents.th:text="${student}"- выводим текущего студента в HTML.
Шаг 3: Запуск приложения
Запустите Spring Boot приложение. Перейдите в браузере на http://localhost:8080/students. Вы увидите динамически сгенерированную страницу со списком студентов.
Работа с динамическими данными
Thymeleaf поддерживает множество выражений для работы с данными. Вот несколько примеров:
Выражения Thymeleaf
| Синтаксис | Описание |
|---|---|
${} |
Выражение для доступа к переменным модели (${student} для доступа к объекту студента) |
th:text |
Устанавливает текст для элемента (<p> -> <p>Текст</p>) |
th:href |
Задает атрибут ссылки (<a> -> <a href="URL">) |
th:if, th:unless |
Условия отображения HTML (th:if="${isLoggedIn}") |
Шаблон с динамическими ссылками
Вот пример, где мы добавляем ссылки для каждого студента:
<ul>
<li th:each="student, iterStat : ${students}">
<a th:href="@{'/students/' + ${iterStat.index}}" th:text="${student}"></a>
</li>
</ul>
Здесь iterStat.index используется для добавления индекса элемента в ссылку.
Практика: создание интерфейса для сущностей
Теперь давайте сделаем серверный рендеринг для сущности, которая была добавлена ранее в нашем приложении.
Шаг 1: Создаем сущность 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;
}
}
Шаг 2: Контроллер для книг
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) {
// Список книг
List<Book> books = List.of(
new Book("Война и мир", "Лев Толстой"),
new Book("Преступление и наказание", "Федор Достоевский"),
new Book("Мастер и Маргарита", "Михаил Булгаков")
);
model.addAttribute("books", books);
return "books";
}
}
Шаг 3: Шаблон для книг books.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Список книг</title>
</head>
<body>
<h1>Список книг</h1>
<table>
<tr>
<th>Название</th>
<th>Автор</th>
</tr>
<tr th:each="book : ${books}">
<td th:text="${book.title}"></td>
<td th:text="${book.author}"></td>
</tr>
</table>
</body>
</html>
Советы и общие ошибки
- Правильно указывайте имя шаблона. Когда возвращается строка из контроллера, она должна соответствовать имени файла в папке
templates. Если файл отсутствует, вы получите ошибкуTemplate not found. - Пространство имен Thymeleaf. Не забывайте добавлять
xmlns:th="http://www.thymeleaf.org"в корневой элемент HTML. Без этого Thymeleaf-направления не будут работать. - Работа с коллекциями. Если передаете коллекцию в модель, убедитесь, что она не
null. В противном случае вы получите ошибку при итерации.
Теперь у вас есть все инструменты для создания динамически генерируемых HTML-страниц с Thymeleaf. Используйте это знание для улучшения вашего приложения! 🎉
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ