Перейти к основному содержимому

Введение в использование Thymeleaf весной

· 7 мин. чтения

1. Обзор

Thymeleaf — это механизм шаблонов Java для обработки и создания HTML, XML, JavaScript, CSS и текста.

В этом руководстве мы обсудим, как использовать Thymeleaf с Spring , а также некоторые основные варианты использования на уровне представления приложения Spring MVC.

Библиотека чрезвычайно расширяема, а ее естественная возможность создания шаблонов гарантирует, что мы можем создавать прототипы шаблонов без серверной части. Это делает разработку очень быстрой по сравнению с другими популярными механизмами шаблонов, такими как JSP.

2. Интеграция Thymeleaf с Spring

Во-первых, давайте посмотрим, какие конфигурации необходимы для интеграции с Spring. Для интеграции требуется библиотека thymeleaf-spring .

Мы добавим следующие зависимости в наш файл Maven POM:

<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>

Обратите внимание, что для проекта Spring 4 мы должны использовать библиотеку thymeleaf-spring4 вместо thymeleaf-spring5 .

Класс SpringTemplateEngine выполняет все этапы настройки.

Мы можем настроить этот класс как bean-компонент в файле конфигурации Java:

@Bean
@Description("Thymeleaf Template Resolver")
public ServletContextTemplateResolver templateResolver() {
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver();
templateResolver.setPrefix("/WEB-INF/views/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode("HTML5");

return templateResolver;
}

@Bean
@Description("Thymeleaf Template Engine")
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setTemplateEngineMessageSource(messageSource());
return templateEngine;
}

Префикс и суффикс свойств bean - компонента templateResolver указывают расположение страниц просмотра в каталоге веб-приложения и расширение их имени файла соответственно. ``

Интерфейс ViewResolver в Spring MVC сопоставляет имена представлений, возвращаемые контроллером, с фактическими объектами представлений. ThymeleafViewResolver реализует интерфейс ViewResolver и используется для определения того, какие представления Thymeleaf отображать, учитывая имя представления.

Последним шагом в интеграции является добавление ThymeleafViewResolver в качестве bean-компонента:

@Bean
@Description("Thymeleaf View Resolver")
public ThymeleafViewResolver viewResolver() {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
viewResolver.setOrder(1);
return viewResolver;
}

3. Лист тимьяна в Spring Boot

Spring Boot обеспечивает автоматическую настройку Thymeleaf , добавляя зависимость spring-boot-starter-thymeleaf :

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>

Никакой явной конфигурации не требуется. По умолчанию файлы HTML должны размещаться в папке ресурсов/шаблонов .

4. Отображение значений из источника сообщения (файлы свойств)

Мы можем использовать атрибут тега th:text="#{key}" для отображения значений из файлов свойств.

Чтобы это работало, нам нужно настроить файл свойств как bean-компонент messageSource :

@Bean
@Description("Spring Message Resolver")
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}

Вот HTML-код Thymeleaf для отображения значения, связанного с ключом welcome.message :

<span th:text="#{welcome.message}" />

5. Отображение атрибутов модели

5.1. Простые атрибуты

Мы можем использовать атрибут тега th:text="${attributename}" для отображения значения атрибутов модели.

Добавим атрибут модели с именем serverTime в класс контроллера:

model.addAttribute("serverTime", dateFormat.format(new Date()));

А вот HTML-код для отображения значения атрибута serverTime :

Current time is <span th:text="${serverTime}" />

5.2. Атрибуты коллекции

Если атрибут модели представляет собой набор объектов, мы можем использовать атрибут тега th:each для итерации по нему.

Давайте определим класс модели Student с двумя полями, id и name :

public class Student implements Serializable {
private Integer id;
private String name;
// standard getters and setters
}

Теперь мы добавим список студентов в качестве атрибута модели в класс контроллера:

List<Student> students = new ArrayList<Student>();
// logic to build student data
model.addAttribute("students", students);

Наконец, мы можем использовать код шаблона Thymeleaf для перебора списка студентов и отображения всех значений полей:

<tbody>
<tr th:each="student: ${students}">
<td th:text="${student.id}" />
<td th:text="${student.name}" />
</tr>
</tbody>

6. Условная оценка

6.1. если и если

Мы используем атрибут th:if="${condition}" для отображения части представления, если условие выполнено. И мы используем атрибут th:unless="${condition}" для отображения части представления, если условие не выполняется.

Давайте добавим поле пола в модель Student :

public class Student implements Serializable {
private Integer id;
private String name;
private Character gender;

// standard getters and setters
}

Предположим, что это поле имеет два возможных значения (M или F), чтобы указать пол учащегося.

Если мы хотим отобразить слова «Мужской» или «Женский» вместо одного символа, мы могли бы сделать это, используя этот код Thymeleaf:

<td>
<span th:if="${student.gender} == 'M'" th:text="Male" />
<span th:unless="${student.gender} == 'M'" th:text="Female" />
</td>

6.2. переключатель и случай

Мы используем атрибуты th:switch и th:case для условного отображения контента с помощью структуры оператора switch.

Давайте перепишем предыдущий код, используя атрибуты th:switch и th:case :

<td th:switch="${student.gender}">
<span th:case="'M'" th:text="Male" />
<span th:case="'F'" th:text="Female" />
</td>

7. Обработка пользовательского ввода

Мы можем обрабатывать ввод формы, используя атрибуты th:action="@{url}" и th:object="${object}" . Мы используем th:action для предоставления URL-адреса действия формы и th:object для указания объекта, к которому будут привязаны отправленные данные формы.

Отдельные поля сопоставляются с использованием атрибута th:field="*{name}" , где имя является совпадающим свойством объекта.

Для класса Student мы можем создать форму ввода:

<form action="#" th:action="@{/saveStudent}" th:object="${student}" method="post">
<table border="1">
<tr>
<td><label th:text="#{msg.id}" /></td>
<td><input type="number" th:field="*{id}" /></td>
</tr>
<tr>
<td><label th:text="#{msg.name}" /></td>
<td><input type="text" th:field="*{name}" /></td>
</tr>
<tr>
<td><input type="submit" value="Submit" /></td>
</tr>
</table>
</form>

В приведенном выше коде /saveStudent — это URL-адрес действия формы, а студент — это объект, который содержит отправленные данные формы.

Класс StudentController обрабатывает отправку формы:

@Controller
public class StudentController {
@RequestMapping(value = "/saveStudent", method = RequestMethod.POST)
public String saveStudent(@ModelAttribute Student student, BindingResult errors, Model model) {
// logic to process input data
}
}

Аннотация @RequestMapping сопоставляет метод контроллера с URL-адресом, указанным в форме. Аннотированный метод saveStudent() выполняет необходимую обработку отправленной формы. Наконец, аннотация @ModelAttribute связывает поля формы с объектом ученика .

8. Отображение ошибок проверки

Мы можем использовать функцию #fields.hasErrors() , чтобы проверить, есть ли в поле какие-либо ошибки проверки. И мы используем функцию #fields.errors() для отображения ошибок для определенного поля. Имя поля является входным параметром для обеих этих функций.

Давайте взглянем на HTML-код для итерации и отображения ошибок для каждого из полей в форме:

<ul>
<li th:each="err : ${#fields.errors('id')}" th:text="${err}" />
<li th:each="err : ${#fields.errors('name')}" th:text="${err}" />
</ul>

Вместо имени поля вышеуказанные функции принимают подстановочный знак * или константу all для обозначения всех полей. Мы использовали атрибут th:each для итерации множественных ошибок, которые могут присутствовать в каждом из полей.

Вот предыдущий код HTML, переписанный с использованием подстановочного знака * :

<ul>
<li th:each="err : ${#fields.errors('*')}" th:text="${err}" />
</ul>

И здесь мы используем константу all :

<ul>
<li th:each="err : ${#fields.errors('all')}" th:text="${err}" />
</ul>

Точно так же мы можем отображать глобальные ошибки в Spring, используя глобальную константу.

Вот код HTML для отображения глобальных ошибок:

<ul>
<li th:each="err : ${#fields.errors('global')}" th:text="${err}" />
</ul>

Кроме того, мы можем использовать атрибут th:errors для отображения сообщений об ошибках.

Предыдущий код для отображения ошибок в форме можно переписать, используя атрибут th:errors :

<ul>
<li th:errors="*{id}" />
<li th:errors="*{name}" />
</ul>

9. Использование конверсий

Мы используем синтаксис двойной скобки {{}} для форматирования данных для отображения. При этом используются модули форматирования , настроенные для этого типа поля в bean-компоненте convertService файла контекста.

Давайте посмотрим, как отформатировать поле имени в классе Student :

<tr th:each="student: ${students}">
<td th:text="${{student.name}}" />
</tr>

В приведенном выше коде используется класс NameFormatter , настроенный путем переопределения метода addFormatters() из интерфейса WebMvcConfigurer .

Для этого наш класс @Configuration переопределяет класс WebMvcConfigurerAdapter :

@Configuration
public class WebMVCConfig extends WebMvcConfigurerAdapter {
// ...
@Override
@Description("Custom Conversion Service")
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new NameFormatter());
}
}

Класс NameFormatter реализует интерфейс Spring Formatter .

Мы также можем использовать утилиту #conversions для преобразования объектов для отображения. Синтаксис служебной функции: #conversions.convert(Object, Class), где объект преобразуется в тип класса .

Вот как отобразить процентное поле студенческого объекта с удаленной дробной частью: ``

<tr th:each="student: ${students}">
<td th:text="${#conversions.convert(student.percentage, 'Integer')}" />
</tr>

10. Заключение

В этой статье мы увидели, как интегрировать и использовать Thymeleaf в приложении Spring MVC.

Мы также видели примеры того, как отображать поля, принимать ввод, отображать ошибки проверки и преобразовывать данные для отображения.

Рабочая версия кода, показанного в этой статье, доступна в репозитории GitHub .