В предыдущей статье я упомянул движок Thymeleaf, используемый в проекте для построения HTML-страниц. Я решил написать отдельный пост, посвящённый только Thymeleaf, а не углубляться в описание данной библиотеки в рамках той статьи, так как она получилась и без того достаточно большой.
Thymeleaf является хорошей заменой JSP и использует в качестве шаблонов валидные файлы XHTML и XML. Для использования Thymeleaf в шаблоне должно быть подключено пространство имён http://www.thymeleaf.org. Для HTML это будет выглядеть следующим образом:
1 |
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org/"> |
После подключения пространства имён в шаблоне можно использовать теги и атрибуты, предоставляемые библиотекой.
Подстановка значений в шаблон
Самый элементарный пример подстановки значения в шаблон:
1 |
<h1 th:text="${greeting}">Hello!</h1> |
В данном случае вместо Hello! в шаблон будет подставлено значение переменной greeting. Обратите внимание, что Thymeleaf подставляет значения только в атрибуты из собственного пространства имён, при этом существующее значение атрибута будет заменено значением, полученным от Thymeleaf. Таким образом шаблон
1 |
<input value="One" th:value="'Two'"/> |
будет преобразован в
1 |
<input value="Two"/> |
Подстановка значений в строку
Кроме подстановки значений в атрибуты есть возможность подставлять значения прямо в текст при помощи двух пар квадратных скобок: [[…]]. Единственное условие — в одном из родительских элементов нужно указать атрибут th:inline, который в качестве значения может принимать text, javascript и none. Например:
1 2 3 |
<body th:inline="text"> <h1>Hello [[${user.name}]]!</h1> </body> |
Выражения
Thymeleaf предоставляет несколько вариантов выражений для различных ситуаций:
- ${…} — выражение, вставляющее в шаблон результат выполнения операции внутри фигурных скобок. Проще говоря, это стандартное OGNL-выражение. Данный тип выражений является наиболее часто используемым.
- *{…} — выражение выделения/выбора. Данный тип выражения позволяет уменьшить количество кода шаблона, предоставляя доступ к свойствам выбранного объекта. Допустим, у нас есть следующий Java-класс:
1234public class Person {String name;String address;}
Мы можем вывести свойства объекта следующим образом:
1234<ul th:object="${person}"><li>Name: <span th:text="*{name}"></span></li><li>Address: <span th:text="*{address}"></span></li></ul>
вместо
1234<ul><li>Name: <span th:text="${person.name}"></span></li><li>Address: <span th:text="${person.address}"></span></li></ul>
Данный способ очень удобен при работе с большим количеством свойств. - #{…} — выражение интернационализации. Thymeleaf подставляет вместо переданного аргумента соответствующее сообщение из файла локализации.Внутри фигурных скобок допускаются дополнительные операции, а также есть возможность передачи аргументов. Допустим, у нас есть следующий файл локализации:
123msg.hello=Hello world!prefixed.msg.hello=Hello prefixed world!msg.hello.user=Hello {0}!
в контексте объявлены переменные prefix=prefixed. и name=Mate и шаблон
123<h1 th:text="#{msg.hello}"></h1><h1 th:text="#{${prefix} + 'msg.hello'}">Hello</h1><h1 th:text="#{msg.hello.user(${name})}"></h1>
В результате будет получен следующий HTML-код:
123<h1>Hello world!</h1><h1>Hello prefixed world!</h1><h1>Hello Mate!</h1> - @{…} — ссылочные выражения. При помощи данного типа выражений можно создавать ссылки, которые можно использовать в тегах a, img, script, form и других. Примеры использования:
123<a th:href="@{/home}">Home</a><a th:href="@{/messages(page=${page + 1})}">Messages</a><a th:href="@{/users/{id}/profile(id=${user.id})}">Profile</a>
Данные ссылки будут преобразованы в:
123<a href="/ourapp/home">Home</a><a href="/ourapp/messages?page=2}">Messages</a><a href="/ourapp/users/1/profile">Profile</a>
Ссылки будут строиться относительно контекстного пути нашего приложения. Ссылки можно генерировать относительно контекстного пути приложения (@{../some/path}), относительно корня сервера (@{~/some/path}) или относительно протокола (@{//example.com}). - ~{…} — фрагментарные выражения, с помощью которых можно вставлять директивами th:insert и th:replace отдельные части шаблнонов. Например, вставка в шаблон навигации из другого шаблона:
12<header th:insert="~{partial/menu :: nav}"></header>
Итеративный обход данных
Как и в любой другой библиотеке для работы с шаблонами, в Thymeleaf есть возможность интеративного обхода набора данных. Допустим, у нас есть переменная persons, которая является коллекцией. Мы можем обойти её следующим образом:
1 2 3 |
<ul th:each="person : ${persons}"> <li th:text="${person.name}"></li> </ul> |
В качестве набора данных могут выступать реализации java.util.Iterable, java.util.Map, массивы, а также любые объекты, но в последнем случае набор будет состоять из одного элемента.
В левой части выражения может быть объявлена ещё одна переменная, через которую можно будет получить доступ к свойствам итерации:
1 2 3 |
<ul th:each="person,stat : ${persons}"> <li th:text="${stat.count} + '. ' + ${person.name}"></li> </ul> |
Данная переменная имеет следующие свойства:
- index — счётчик итерации, начинающийся с 0
- count — счётчик итерации, начинающийся с 1
- size — общее количество элементов в коллекции
- current — свойства текущей итерации
- even/odd — свойства, с помощью которых можно проверить чётность итерации
- first/last — свойства, с помощью которых можно проверить, что текущий элемент — первый или последний элемент коллекции
Условные операторы
Thymeleaf предоставляет два условных оператора, применимых в шаблонах.
Первый оператор — if и его инвертированный аналог — unless. Пример использования данных операторов:
1 2 3 4 5 6 |
<div th:if="${user.isAdmin}"> Admin block </div> <div th:unless="${user.isAdmin}"> Non-admin block </div> |
Второй оператор — switch/case. Пример использования:
1 2 3 4 5 |
<ul th:switch="${user.role}"> <li th:case="'admin'">Admin</li> <li th:case="#{app.roles.moderator}">Moderator</li> <li th:case="*">User</li> </ul> |