«1. Введение
В этом уроке мы рассмотрим переменные в Thymeleaf. Мы создадим пример Spring Boot, который будет получать список статей Baeldung и отображать их в HTML-шаблоне Thymeleaf.
2. Зависимости Maven
Для работы с Thymeleaf нам нужно добавить зависимости spring-boot-starter-thymeleaf и spring-boot-starter-web:
<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>
3. Веб-контроллер ~ ~~ Сначала мы создадим веб-контроллер с конечной точкой GET, который возвращает страницу со списком статей Baeldung.
Метод, аннотированный @GetMapping, будет принимать единственный параметр — Модель. Он содержит все глобальные переменные, которые можно в дальнейшем использовать внутри шаблона Thymeleaf. В нашем случае у модели будет всего один параметр — список статей.
Класс Article будет состоять из двух строковых полей, имени и URL-адреса:
Возвращаемым значением метода нашего контроллера должно быть имя желаемого шаблона Thymeleaf. Это имя должно соответствовать файлу HTML, расположенному в каталоге src/resource/template. В нашем случае это будет src/resource/template/articles-list.html.
public class Article {
private String name;
private String url;
// constructor, getters and setters
}
Давайте взглянем на наш контроллер Spring:
После запуска приложения страница статей будет доступна по адресу http://localhost:8080/articles.
@Controller
@RequestMapping("/api/articles")
public class ArticlesController {
@GetMapping
public String allArticles(Model model) {
model.addAttribute("articles", fetchArticles());
return "articles-list";
}
private List<Article> fetchArticles() {
return Arrays.asList(
new Article(
"Introduction to Using Thymeleaf in Spring",
"https://www.baeldung.com/thymeleaf-in-spring-mvc"
),
// a few other articles
);
}
}
4. Шаблон Thymeleaf
Теперь давайте перейдем к HTML-шаблону Thymeleaf. Он должен иметь стандартную структуру HTML-документа только с дополнительным определением пространства имен Thymeleaf:
Мы будем использовать его в качестве шаблона в дальнейших примерах, где мы будем заменять только содержимое тега \u003cmain\u003e:
<html xmlns:th="http://www.thymeleaf.org">
5. Определение переменных
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Thymeleaf Variables</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<main>
...
</main>
</body>
</html>
Есть два способа определить переменную в шаблоне Thymeleaf. Первый вариант — взять один элемент при переборе массива:
В результате мы получим \u003cdiv\u003e с несколькими элементами \u003ca\u003e, соответствующими количеству статей в переменной article.
<div th:each="article : ${articles}">
<a th:text="${article.name}" th:href="${article.url}"></a>
</div>
Другой способ — определить новую переменную на основе другой. Например, мы можем взять первый элемент массива статей:
Или мы можем создать новую переменную, содержащую только название статьи:
<div th:with="firstArticle=${articles[0]}">
<a th:text="${firstArticle.name}" th:href="${firstArticle.url}"></a>
</div>
В приведенном выше примере ${article. name} и ${articleName} фрагменты являются заменяемыми.
<div th:each="article : ${articles}", th:with="articleName=${article.name}">
<a th:text="${articleName}" th:href="${article.url}"></a>
</div>
Также можно определить несколько переменных. Например, мы можем создать две отдельные переменные для хранения названия статьи и URL-адреса:
6. Область действия переменных
<div th:each="article : ${articles}" th:with="articleName=${article.name}, articleUrl=${article.url}">
<a th:text="${articleName}" th:href="${articleUrl}"></a>
</div>
Переменные, передаваемые в модель в контроллере, имеют глобальную область действия. Это означает, что их можно использовать в любом месте наших HTML-шаблонов.
С другой стороны, переменные, определенные в шаблоне HTML, имеют локальную область видимости. Их можно использовать только в пределах диапазона элемента, в котором они были определены.
Например, приведенный ниже код корректен, так как элемент \u003ca\u003e находится внутри firstDiv:
С другой стороны, когда мы пытаемся использовать firstArticle в другом div:
<div id="firstDiv" th:with="firstArticle=${articles[0]}">
<a th:text="${firstArticle.name}" th:href="${firstArticle.url}"></a>
</div>
Мы получим исключение во время компиляции, говорящее, что firstArticle имеет значение null:
<div id="firstDiv" th:with="firstArticle=${articles[0]}">
<a th:text="${firstArticle.name}" th:href="${firstArticle.url}"></a>
</div>
<div id="secondDiv">
<h2 th:text="${firstArticle.name}"></h2>
</div>
Это потому, что элемент \u003ch2\u003e пытается использовать переменную, определенную в firstDiv, которая выходит за рамки.
org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'name' cannot be found on null
Если нам по-прежнему нужно использовать переменную firstArticle внутри secondDiv, нам нужно снова определить ее во secondDiv или обернуть эти два тега div в общий элемент и определить в нем firstArticle.
7. Изменение значения переменной
Также можно перезаписать значение переменной в заданной области:
В приведенном выше примере мы переопределили переменную article так, чтобы она содержала только два первых элемента.
<div id="mainDiv" th:with="articles = ${ { articles[0], articles[1] } }">
<div th:each="article : ${articles}">
<a th:text="${article.name}" th:href="${article.url}"></a>
</div>
</div>
Обратите внимание, что за пределами mainDiv исходное значение переменной article будет передано в контроллер.
8. Заключение
В этом уроке мы узнали, как определять и использовать переменные в Thymeleaf. Как всегда, весь исходный код доступен на GitHub.
«