1. Введение
В этом уроке мы рассмотрим переменные в Thymeleaf . Мы создадим пример Spring Boot, который будет получать список статей ForEach и отображать их в 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, который возвращает страницу со списком статей ForEach.
Метод, аннотированный @GetMapping
, будет принимать единственный параметр — Model
. Он содержит все глобальные переменные, которые можно в дальнейшем использовать внутри шаблона Thymeleaf. В нашем случае у модели будет всего один параметр — список статей.
Класс Article
будет состоять из двух полей String ,
name
и url
:
public class Article {
private String name;
private String url;
// constructor, getters and setters
}
Возвращаемое значение метода нашего контроллера должно быть именем желаемого шаблона Thymeleaf. Это имя должно соответствовать файлу HTML, расположенному в каталоге src/resource/template
. В нашем случае это будет src/resource/template/articles-list.html
.
Давайте быстро взглянем на наш контроллер Spring:
@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.foreach.com/thymeleaf-in-spring-mvc"
),
// a few other articles
);
}
}
После запуска приложения страница статей будет доступна по адресу http://localhost:8080/articles
.
4. Шаблон листа тимьяна
Теперь давайте перейдем к HTML-шаблону Thymeleaf. Он должен иметь стандартную структуру HTML-документа только с дополнительным определением пространства имен Thymeleaf:
<html xmlns:th="http://www.thymeleaf.org">
Мы будем использовать его в качестве шаблона в дальнейших примерах, где мы будем заменять только содержимое тега <main>
:
<!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>
5. Определите переменные
Есть два способа определить переменную в шаблоне Thymeleaf. Первый вариант — взять один элемент при переборе массива:
<div th:each="article : ${articles}">
<a th:text="${article.name}" th:href="${article.url}"></a>
</div>
В результате мы получим <div>
с несколькими элементами <a>
, соответствующими количеству статей в переменной
article.
Другой способ — определить новую переменную на основе другой. Например, мы можем взять первый элемент массива статей:
<div th:with="firstArticle=${articles[0]}">
<a th:text="${firstArticle.name}" th:href="${firstArticle.url}"></a>
</div>
Или мы можем создать новую переменную, содержащую только название статьи:
<div th:each="article : ${articles}", th:with="articleName=${article.name}">
<a th:text="${articleName}" th:href="${article.url}"></a>
</div>
В приведенном выше примере фрагменты ${article.name }
и ${articleName}
являются заменяемыми.
Также возможно определить несколько переменных. Например, мы можем создать две отдельные переменные для хранения названия статьи и URL-адреса:
<div th:each="article : ${articles}" th:with="articleName=${article.name}, articleUrl=${article.url}">
<a th:text="${articleName}" th:href="${articleUrl}"></a>
</div>
6. Область действия переменных
Переменные, передаваемые в модель
в контроллере, имеют глобальную область действия. Это означает, что их можно использовать в любом месте наших HTML-шаблонов.
С другой стороны, переменные, определенные в шаблоне HTML, имеют локальную область действия. Их можно использовать только в пределах диапазона элемента, в котором они были определены.
Например, приведенный ниже код верен, так как элемент <a> находится внутри
firstDiv
:
<div id="firstDiv" th:with="firstArticle=${articles[0]}">
<a th:text="${firstArticle.name}" th:href="${firstArticle.url}"></a>
</div>
С другой стороны, когда мы пытаемся использовать firstArticle
в другом div
:
<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>
Мы получим исключение во время компиляции, говорящее, что firstArticle
равно null
:
org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'name' cannot be found on null
Это связано с тем, что элемент <h2>
пытается использовать переменную, определенную в firstDiv,
которая находится вне области действия.
Если нам по-прежнему нужно использовать переменную firstArticle
внутри secondDiv
, нам нужно будет снова определить ее в secondDiv
или обернуть эти два тега div
в общий элемент и определить в нем firstArticle
.
7. Изменение значения переменной
Также возможно перезаписать значение переменной в заданной области:
<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>
В приведенном выше примере мы переопределили переменную
article, чтобы иметь только два первых элемента.
Обратите внимание, что за пределами mainDiv
исходное
значение переменной article будет передано в контроллер.
8. Заключение
В этом руководстве мы узнали, как определять и использовать переменные в Thymeleaf. Как всегда, весь исходный код доступен на GitHub .