Диалект Layout — это диалект Thymeleaf, который позволяет пользователям создавать макеты и шаблоны для повторного использования HTML кода. Он имеет иерархический подход и использует шаблон декоратора для «декорирования» файлов макета. Layout Dialect является отдельным проектом и не поставляется с Thymeleaf. Тем не менее, это открытый исходный код, доступный на GitHub, он хорошо документирован и, как кажется, также поддерживается в хорошем состоянии.
Установка
Нам нужно будет добавить стартовый пакет Thymeleaf к вашему Spring Boot pom:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Однако, начиная с Spring Boot 2, этого уже недостаточно. Pom диалекта не является частью Spring Boot, и мы должны добавить его самостоятельно:
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
<version>2.3.0</version>
</dependency>
В примерах кода также используется Bootstrap, поэтому необходимо также добавить веб-файлы:
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.0.0</version>
</dependency>
В качестве последнего шага нам нужно создать bean-компонент LayoutDialect в аннотированном классе @Configuration.
@Bean
public LayoutDialect layoutDialect() {
return new LayoutDialect();
}
Пошли далее.
Layout Dialect пример
Этот пример покажет, как мы можем использовать Layout Dialect, чтобы определить макеты для наших страниц, чтобы мы могли лучше использовать код повторно: с помощью страницы index.html, которая использует layout.html в качестве макета. Имя Layout.html — произвольное и может быть любым. Там добавлено еще несколько файлов, но они только для демонстрации.
На картинке структура папки ресурсов. Spring Boot автоматически найдет все шаблоны Thymeleaf в каталоге resources/templates.
Layout.html
<!DOCTYPE html>
<html>
<head>
<title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE">Igorski.co</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link th:href="@{/webjars/bootstrap/4.0.0/css/bootstrap.min.css}" rel="stylesheet" media="screen" />
</head>
<body>
<div th:replace="fragments/header :: header"> This header content is going to be replaced.</div>
<div class="container">
<div class="row">
<div class="col-2" layout:fragment="sidebar">
<h1>This is the layout's sidebar</h1>
<p>This content will be replaced if the page
using the layout also defines a layout:fragment="sidebar" segment.</p>
</div>
<div class="col" layout:fragment="content">
<h1>This is the Layout's main section</h1>
<p>This content will be replaced if the page
using the layout also defines a layout:fragment="content" segment. </p>
</div>
</div>
</div>
<footer th:insert="fragments/footer :: footer" class="footer">
This content will remain, but other content will be inserted after it.
</footer>
</body>
</html>
В layout.html используются два из пяти процессоров, представленных в Layout Dialect. Во-первых, это макет: процессор шаблонов заголовков. Процессор шаблона заголовка помогает пользователю определить лучший заголовок для получающейся страницы. В этом примере он определяет окончательный заголовок как комбинацию заголовка страницы и заголовка макета. Для этого используются два специальных токена, представленных в Layout Dialect, $LAYOUT_TITLE и $CONTENT_TITLE.
Наибольшее значение в layout.html имеют два заполнителя (или фрагмента), определенных макетом: процессор фрагмента. Этот процессор позволяет нам определять заполнители контента в наших макетах. Содержимое этих заполнителей будет позже заменено содержимым страниц, использующих макет. В примере определены два разных фрагмента, один для боковой панели, а другой для основного контента. Мы, однако, можем иметь столько фрагментов, сколько пожелаем, при условии, что все они имеют разные имена.
Index.html
<!DOCTYPE html>
<html xmlns:layout="http://www.w3.org/1999/xhtml" layout:decorate="~{layouts/layout}">
<head>
<title>Home Page</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link th:href="@{/css/core.css}" rel="stylesheet" media="screen" />
</head>
<body>
<div class="container">
<div class="row">
<div class="col-2" layout:fragment="sidebar">
<h1>Sidebar</h1>
<a href="#">Login</a>
</div>
<div class="col" layout:fragment="content">
<h1>Welcome to the Index page</h1>
<br>This content is replacing the content of the layout:fragment="content"<br>
placeholder in layout.html</p>
</div>
</div>
</div>
</body>
</html>
Мы заявляем, что index.html использует layout.html в качестве своего макета с процессором layout: decorate. Сделав это, мы объявляем, что index.html будет использовать шаблон layout.html. Здесь самое главное — использование процессора фрагментов. Он указывает содержимое, которое будет использоваться вместо содержимого фрагментов макета с тем же именем. Еще одна вещь, которую стоит упомянуть, это заголовок. На полученной странице index.html, которую мы получим, после обработки заголовок будет представлять собой комбинацию двух заголовков, один из index.html, а другой из макета. Они будут объединены.
Как layout.html, так и index.html можно просматривать в браузере без какой-либо обработки. Но после обработки мы видим, что index.html сильно отличается. Содержимое index.html используется для оформления макета и размещения содержимого внутри макета на основе того, что определяет макет.
В примере присутствуют два других элемента: верхний и нижний колонтитулы. Однако они используют процессоры Thymeleaf Standard Layout th:replace и th:insert. Очень похожи на последние два из пяти процессоров, представленных в Layout Dialect, layout:insert и layout:replace. Они более или менее делают то же самое. В отличие от предыдущих процессоров, которые мы обсуждали, эти два используют не иерархический, а включающий подход. Это больше характерно для типовой формы Thymeleaf.
На картинке окончательный вид страницы. Он имеет как верхний, так и нижний колонтитулы, хотя ни один из них не упоминается в разметке index.html.
Автор: Константин