1. Введение
Thymeleaf — это механизм шаблонов Java, способный напрямую работать с Spring. Чтобы познакомиться с Thymeleaf и Spring, ознакомьтесь с этой статьей .
Помимо этих основных функций, Thymeleaf предлагает нам набор служебных объектов, которые помогут нам выполнять общие задачи в нашем приложении.
В этом руководстве мы обсудим обработку и форматирование новых и старых классов Java Date
с несколькими функциями Thymeleaf 3.0.
2. Зависимости Maven
Во-первых, давайте создадим конфигурацию для интеграции Thymeleaf с Spring в наш pom.xml
:
<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>
Последние версии thymeleaf
и thymeleaf-spring5
можно найти на Maven Central. Обратите внимание, что для проекта Spring 4 вместо тимелеаф-спринг5
необходимо использовать библиотеку тимелеаф-спринг4
.
Более того, чтобы работать с новыми классами Date
Java 8 , нам нужно добавить еще одну зависимость в наш pom.xml
:
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
Дополнительные функции thymeleaf
— это дополнительный модуль, полностью поддерживаемый официальной командой Thymeleaf, который был создан для совместимости с Java 8 Time API. Он добавляет # временной
объект в контекст
в качестве обработчика служебных объектов во время оценки выражений. Это означает, что его можно использовать для оценки выражений на языке навигации по графам объектов (OGNL) и языке выражений Spring (SpringEL).
3. Старое и новое: java.util
и java.time
Пакет Time
— это новый API даты, времени и календаря для платформы Java SE. Основное различие между этим новым API и старым устаревшим API Date
заключается в том, что новый API различает машинное и человеческое представление временной шкалы. Машинное представление показывает последовательность целочисленных значений относительно эпохи
, тогда как человеческое представление показывает набор полей (например, год, месяц и день).
Для работы с новым пакетом Time
нам нужно настроить наш механизм шаблонов для использования нового Java8TimeDialect
:
private ISpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.addDialect(new Java8TimeDialect());
engine.setTemplateResolver(templateResolver);
return engine;
}
Это добавит объект #temporal
, аналогичный объектам в стандартном диалекте, что позволит форматировать и создавать временные
объекты из шаблонов Thymeleaf.
Чтобы протестировать обработку новых и старых классов, мы создадим следующие переменные и добавим их как объекты модели в наш класс контроллера:
model.addAttribute("standardDate", new Date());
model.addAttribute("localDateTime", LocalDateTime.now());
model.addAttribute("localDate", LocalDate.now());
model.addAttribute("timestamp", Instant.now());
Теперь мы готовы использовать служебные объекты Thymeleaf Expression
и Temporals
.
3.1. Формат даты
Первая функция, которую мы хотим охватить, — это форматирование объекта Date
(который добавляется к параметрам модели Spring). Мы будем использовать формат ISO8601
:
<h1>Format ISO</h1>
<p th:text="${#dates.formatISO(standardDate)}"></p>
<p th:text="${#temporals.formatISO(localDateTime)}"></p>
<p th:text="${#temporals.formatISO(localDate)}"></p>
<p th:text="${#temporals.formatISO(timestamp)}"></p>
Независимо от того, как наша дата
была установлена на стороне сервера, она будет отображаться в Thymeleaf в соответствии с выбранным стандартом. StandardDate будет обрабатываться утилитой #
date
. Новые классы LocalDateTime
, LocalDate
и Instant
будут обрабатываться утилитой #temporals
.
``
Более того, если мы хотим установить формат вручную, мы можем сделать это с помощью:
<h1>Format manually</h1>
<p th:text="${#dates.format(standardDate, 'dd-MM-yyyy HH:mm')}"></p>
<p th:text="${#temporals.format(localDateTime, 'dd-MM-yyyy HH:mm')}"></p>
<p th:text="${#temporals.format(localDate, 'MM-yyyy')}"></p>
Как мы видим, мы не можем обработать класс Instant с помощью #
temporals.format(…)
— это приведет к UnsupportedTemporalTypeException
. Кроме того, форматирование LocalDate
возможно только в том случае, если мы указываем только определенные поля даты, пропуская поля времени.
Посмотрим конечный результат:
3.2. Получить определенные поля даты
Чтобы получить определенные поля класса java.util.Date
, мы должны использовать следующие служебные объекты:
${#dates.day(date)}
${#dates.month(date)}
${#dates.monthName(date)}
${#dates.monthNameShort(date)}
${#dates.year(date)}
${#dates.dayOfWeek(date)}
${#dates.dayOfWeekName(date)}
${#dates.dayOfWeekNameShort(date)}
${#dates.hour(date)}
${#dates.minute(date)}
${#dates.second(date)}
${#dates.millisecond(date)}
Для нового пакета java.time
мы должны использовать # временные
утилиты:
${#temporals.day(date)}
${#temporals.month(date)}
${#temporals.monthName(date)}
${#temporals.monthNameShort(date)}
${#temporals.year(date)}
${#temporals.dayOfWeek(date)}
${#temporals.dayOfWeekName(date)}
${#temporals.dayOfWeekNameShort(date)}
${#temporals.hour(date)}
${#temporals.minute(date)}
${#temporals.second(date)}
${#temporals.millisecond(date)}
Давайте рассмотрим несколько примеров. Во-первых, давайте покажем сегодняшний день недели:
<h1>Show only which day of a week</h1>
<p th:text="${#dates.day(standardDate)}"></p>
<p th:text="${#temporals.day(localDateTime)}"></p>
<p th:text="${#temporals.day(localDate)}"></p>
Далее покажем название дня недели:
<h1>Show the name of the week day</h1>
<p th:text="${#dates.dayOfWeekName(standardDate)}"></p>
<p th:text="${#temporals.dayOfWeekName(localDateTime)}"></p>
<p th:text="${#temporals.dayOfWeekName(localDate)}"></p>
Наконец, давайте покажем текущую секунду дня:
<h1>Show the second of the day</h1>
<p th:text="${#dates.second(standardDate)}"></p>
<p th:text="${#temporals.second(localDateTime)}"></p>
Обратите внимание, что для работы с частями времени нам нужно будет использовать LocalDateTime
, так как LocalDate
выдаст ошибку.
4. Как использовать средство выбора даты в форме
Давайте посмотрим, как использовать средство выбора даты для отправки значения Date
из формы Thymeleaf .
Во-первых, давайте создадим класс Student
с атрибутом Date :
public class Student implements Serializable {
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthDate;
}
Аннотация @DateTimeFormat
объявляет , что поле BirthdayDate
должно быть отформатировано как Date
.
Далее мы создадим форму Thymeleaf для ввода даты
:
<form th:action="@{/saveStudent}" method="post" th:object="${student}">
<div>
<label for="student-birth-date">Date of birth:</label>
<input type="date" th:field="${student.birthDate}" id="student-birth-date"/>
</div>
<div>
<button type="submit" class="button">Submit</button>
</div>
</form>
Когда мы отправляем форму, контроллер перехватывает объект Student
, отображенный в форме с атрибутом th:object .
Кроме того, атрибут th:field
связывает входное значение с полемbirthDate
.
Теперь давайте создадим контроллер для перехвата POST
- запроса:
@RequestMapping(value = "/saveStudent", method = RequestMethod.POST)
public String saveStudent(Model model, @ModelAttribute("student") Student student) {
model.addAttribute("student", student);
return "datePicker/displayDate.html";
}
После того, как мы отправим форму, мы отобразим значение BirthdayDate
на другой странице с шаблоном dd/MM/yyyy
:
<h1>Student birth date</h1>
<p th:text="${#dates.format(student.birthDate, 'dd/MM/yyyy')}"></p>
Результат показывает нашу форму с выбором даты:
После отправки формы мы увидим выбранную дату:
5. Вывод
В этом кратком руководстве мы обсудили функции обработки даты
Java , реализованные в платформе Thymeleaf версии 3.0.
Как проверить? Мы предлагаем сначала поиграть с кодом в браузере, а затем также проверить наши существующие тесты JUnit.
Обратите внимание, что наши примеры не охватывают все доступные параметры в Thymeleaf. Если вы хотите узнать обо всех типах утилит, взгляните на нашу статью о Spring и Thymeleaf Expressions .
Полную реализацию этого руководства можно найти на GitHub .