«1. Введение

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

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

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

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

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

Добавьте следующие зависимости в ваш POM-файл Maven:

<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 указывают расположение страниц просмотра в каталоге webapp и расширение их имени файла соответственно.

Интерфейс 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. Thymeleaf в Spring Boot

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

<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 в класс контроллера:

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

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

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

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

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

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

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

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

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

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

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

6.1. если и если не

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

Добавьте поле «пол» в модель «Студент»:

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

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

6.2. switch и case

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

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

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

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

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

«Ввод формы может быть обработан с помощью атрибутов th:action=†@{url}†и th:object=†${object}â€. th:action используется для предоставления URL-адреса действия формы, а th:object используется для указания объекта, к которому будут привязаны отправленные данные формы. Отдельные поля сопоставляются с использованием атрибута th:field=» *{name}», где имя является совпадающим свойством объекта.

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

В приведенном выше коде /saveStudent — это URL-адрес действия формы, а 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>

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

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

@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
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Поле имени в классе Student отформатировано:

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

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

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

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

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

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

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

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

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

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

«