Рубрики
Без рубрики

Начало работы с Thymeleaf на Java и весной

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

Автор оригинала: Dhrubajyoti Bhattacharjee.

Вступление

При разработке веб – приложений важным выбором является то, какой движок будет заботиться о слое представления.

Страницы сервера Java (JSP) раньше были очень популярны, хотя их использование требовало больших затрат времени и затрат времени. Они потребовали значительных изменений в HTML-формате страниц.

В настоящее время Thymeleaf широко используется и используется в качестве механизма создания шаблонов для приложений Spring/MVC. Он также может быть использован для создания шаблонов электронной почты в формате HTML. В то время как JSP компилируются в классы сервлетов Java, Thymeleaf анализирует простые файлы шаблонов HTML. На основе выражений, присутствующих в файле, он генерирует статическое содержимое. Он способен обрабатывать HTML, XML, JS, CSS и т.д.

Стандартные диалекты Тимелифа

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

Давайте взглянем на самый важный сегмент диалекта – Стандартные функции выражения . Вот некоторые из выражений, которые вы будете использовать довольно регулярно:

  • Выражения переменных: ${...}
  • Выражения переменных выбора: *{...}
  • Выражения сообщений: #{...}
  • Выражения URL-адресов ссылок: @{...}
  • Выражения фрагментов: ~{...}

Вот некоторые литералы, которые вы, вероятно, будете использовать:

  • Текстовые литералы: "Привет, мир" , "Добро пожаловать в stack abuse" ,…
  • Числовые литералы: 0 , 123 , 67.90 , …
  • Логические литералы: true , false
  • Нулевой литерал: null

Основные операции:

  • Объединение строк: +

  • Буквальные замены: |Добро пожаловать в ${город}|

  • Двоичные операторы: + , - , * , / , `%

  • Двоичные операторы: и , или

  • Логическое отрицание (унарный оператор): ! , не

Сравнения:

  • Компараторы: > , < , >= , <= ( gt , lt , ge , le )
  • Операторы равенства: == , != ( эквалайзер , не )

Условные обозначения:

  • Если-тогда: (если) ? (затем)
  • Если-тогда-еще: (если) ? (затем): (еще)
  • По умолчанию: (значение) ?: (значение по умолчанию)

Все эти выражения можно использовать в сочетании друг с другом для получения желаемых результатов.

Зависимость от Тимелифа

Самый простой способ начать работу с Thymeleaf через Maven-включить зависимость:


    org.thymeleaf
    thymeleaf
    ${version}

Или, если вы используете Gradle:

compile group: 'org.thymeleaf', name: 'thymeleaf', version: '${version}'

Механизм шаблонов и распознаватели шаблонов

Для Thymeleaf Распознаватель шаблонов отвечает за загрузку шаблонов из заданного местоположения, в то время как Механизм шаблонов отвечает за его обработку для данного контекста. Нам нужно будет настроить оба в классе конфигурации:

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public ClassLoaderTemplateResolver templateResolver() {
        ClassLoaderTemplateResolver templateResolver = 
                new ClassLoaderTemplateResolver();
        templateResolver.setPrefix("/templates/");
        templateResolver.setSuffix(".html");
        templateResolver.setCharacterEncoding("UTF-8");

        return templateResolver;
    }

    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver());
        return templateEngine;
    }
}

Здесь мы создали экземпляр templateResolver и установили его префикс и суффикс. Представления будут расположены в каталоге /шаблоны и будут заканчиваться на .html .

После этого мы настроили механизм шаблонов , просто установив распознаватель и вернув его.

Давайте проверим, работает ли это, пытаясь обработать сообщение:

StringWriter writer = new StringWriter();
Context context = new Context();
TemplateEngine templateEngine = templateEngine();

context.setVariable("message", "Welcome to thymeleaf article");
templateEngine.process("myTemplate", context, writer);
LOG.info(writer.toString());

Двигатель используется для обработки myTemplate.html файл, расположенный в каталоге src/main/ресурсы/шаблоны . Каталог /ресурсы используется по умолчанию. Переменная передается в контекст , что позволяет нам ссылаться на нее в самом шаблоне:





    

Атрибут th:text оценит значение этого сообщения и вставит его в тело тега, в котором он находится. В нашем случае тело тега :





    

Welcome to thymeleaf article

Отлично работает! Давайте продолжим и настроим ViewResolver , чтобы мы могли заполнять представления с помощью контроллеров, а не жестко кодировать значения в контексте.

Распознаватель видов

Прямо под другой конфигурацией давайте настроим ViewResolver . Он сопоставляет имена представлений с фактическими представлениями. Это позволяет нам просто ссылаться на представления в контроллерах, а не на значения жесткого кодирования:

@Bean
public ViewResolver viewResolver() {
    ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
    viewResolver.setTemplateEngine(templateEngine());
    viewResolver.setCharacterEncoding("UTF-8");
    return viewResolver;
}

Отображение Атрибутов Модели

Самое основное использование большинства движков, таких как Thymeleaf, заключается в отображении определенных свойств/атрибутов моделей. Давайте создадим обработчик запроса, который возвращает объект с набором нескольких полей:

@GetMapping("/article")
public ModelAndView getArticle(ModelAndView modelAndView) {
    Article article = new Article();
    article.setAuthor(getName());
    article.setContent(getArticleContent());
    article.setTitle(getTitle());
    modelAndView.addObject("article", article);
    modelAndView.setViewName("articleView");
    return modelAndView;
}

Обработчик отправляет обратно представление с именем представление статьи и объект с именем статья . Теперь эти два понятия взаимосвязаны. Мы можем получить доступ к статье на странице просмотр статьи . Это похоже на то, как мы вводили сообщение в Контекст объект в прошлый раз.

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






Article title

Author name

contetnt

Используя выражение переменной, ${...} , мы ссылаемся на статью объект и вводим поля в th:текст атрибуты соответственно. Вот как будет выглядеть отрисованная страница:

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

Локальные переменные

Локальные переменные в Thymeleaf очень удобны. Локальные переменные определяются в определенном фрагменте шаблона. Они доступны только в области определяющего фрагмента.

С локальными переменными мы избегаем необходимости делать все в контроллере и выполнять операции на самой странице. Давайте взглянем:


    name
    author
    description

Здесь переменная article является локальной переменной. Он представляет статью объект из списка статьи . Мы не можем ссылаться на переменную article вне таблицы HTML.

Переменная article не была передана контроллером – она была определена на самой странице. th:каждый атрибут будет присваивать новые значения объекту article при каждом проходе списка.

Это выглядело бы примерно так:

Другой способ определения локальных переменных-с помощью атрибута th:с :

This article is writen by John Doe.

Здесь мы определили переменную через th:с в качестве первого элемента списка, передаваемого контроллером. Мы можем ссылаться на эту переменную из тега , в котором она определена.

Аналогично, мы можем определить несколько переменных с помощью одного атрибута th:with :

This article is writen by John Doe.

Category John Doe.

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

Обратите внимание, что мы используем переменную article для получения сведений автора с карты автора. Это позволяет нам повторно использовать переменную в одном и том же атрибуте.

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

@GetMapping("/articles")
public ModelAndView getArticles(ModelAndView modelAndView) {
    modelAndView.addObject("articles", getArticles());
    modelAndView.addObject("authors", getAuthors());
    modelAndView.setViewName("articles");
    return modelAndView;
}

Вам не нужно устанавливать локальные переменные, привязанные к объектам. Вы можете так же легко использовать строковые литералы или цифры:

Hello, !

Выражения Переменных выбора

Что стоит отметить здесь, так это Выражения переменных выбора . Давайте посмотрим, как они работают:

name author description

Вместо того, чтобы писать ${article.name} , ${article.author} и т.д., Мы можем просто поставить *{...} выражение. Атрибут th:object определяет, к какому объекту принадлежат поля, на которые имеются ссылки.

Создание форм и входных данных

Работа с формами происходит часто и является одним из наиболее фундаментальных способов, с помощью которых пользователь может отправлять информацию на наш сервер. Thymeleaf предоставляет различные атрибуты для создания и обработки отправленных форм.

Атрибут th:действие заменяет атрибут HTML действие для <форма> . Атрибут th:объект используется для привязки полей формы к объекту. Это похоже на атрибут модель или имя команды , которое вы обычно используете с JSP.

Давайте взглянем на определение формы:

Здесь, через выражение ссылка , форма отправляет запрос на публикацию по URL-адресу /статьи//. Связанным объектом является статья . Теперь нам нужно будет ввести несколько полей ввода, чтобы мы могли фактически заполнить информацию о статье :

Git Essentials

Ознакомьтесь с этим практическим руководством по изучению Git, содержащим лучшие практики и принятые в отрасли стандарты. Прекратите гуглить команды Git и на самом деле изучите это!

Мы нашли статью в этой форме, поэтому ссылка название и содержание принадлежат ей.

Теперь, как только пользователь введет содержимое в эти поля, мы захотим обработать его и сохранить в базе данных. Давайте создадим обработчик /form , который сначала отобразит форму на странице:

@GetMapping("/form")
public ModelAndView getArticleForm(ModelAndView modelAndView) {
    Article article = new Article();
    modelAndView.addObject("article", article);
    modelAndView.setViewName("articleForm");
    return modelAndView;
}

Мы должны добавить пустой объект article в форму, иначе атрибут th:object будет недействительным. Теперь давайте создадим обработчик запроса на публикацию, в который попадает форма:

@PostMapping("/article")
public String saveArticle(@ModelAttribute Article article) {
    articleService.saveArticle(article);
    return "articles";
}

Здесь аннотация @ModelAttribute привязывает полученную модель к объекту, который ее обрабатывает. Все это упаковано в объект article , который затем сохраняется с помощью классического сервиса, расширяющего CrudRepository .

Хотя такой рудиментарной формы часто бывает недостаточно. Давайте посмотрим, как мы можем добавлять переключатели, флажки, выпадающие меню и т. Д.

Переключатели

Чтобы добавить переключатель, мы создадим классический <ввод> тег и определим его тип с помощью HTML. Задача Thymeleaf заключается в привязке поля и значения этого переключателя к th:объекту формы:

После визуализации это будет выглядеть примерно так:

Флажки

Флажки работают точно так же:

Это выглядело бы так:

Меню Опций

И, наконец, давайте посмотрим, как мы можем использовать некоторые варианты:

Как правило, параметры представлены из списка. В этом случае мы создали <опция> тег для каждой технологии в списке и присвоили технологии значение, которое должен видеть пользователь.

Это выглядело бы примерно так:

Условные Операторы

Веб-сайты не являются статичными. В зависимости от определенных оценок элементы либо отображаются, либо скрываются, заменяются или настраиваются. Например, мы можем выбрать отображение сообщения вместо таблицы, если в базе данных нет строк.

Давайте взглянем на некоторые основные условные операторы в Thymeleaf:


    
Name Author Description Category Date
name author description category date

No data found

th:если используется как обычный если оператор. Если список статьи не пуст, мы заполняем таблицу – если она пуста, мы выводим сообщение. Здесь #список – это служебный объект, используемый для выполнения удобных методов в коллекциях.

Кроме того, у нас также могут быть операторы th:switch и th:case . Они довольно просты:

Отображается только соответствующий регистр.

Экстернализация текста для интернационализации

Из коробки Thymeleaf поставляется с поддержкой интернационализации. Создайте файл my Template.properties в том же каталоге, что и ваши шаблоны.

Давайте создадим сообщение и присвоим ему значение:

welcome.message=Welcome to Stack Abuse

Теперь в любом шаблоне мы можем ссылаться на значение, вызывая welcome.message с выражением Message :


    

Для использования разных языков создайте больше файлов, таких как my Template_de.properties . При создании контекста для шаблона в исходной настройке просто передайте ему языковой стандарт:

Context context = new Context(Locale.GERMAN);

Фрагменты и макеты

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

Этот шаблонный код можно использовать повторно и просто ссылаться на каждой странице. Thymeleaf предлагает нам фрагменты , которые представляют собой отдельные файлы, которые вы можете вставить в другой файл. Давайте создадим фрагмент заголовка и включим его в другой шаблон:


   
    

Welcome to Stack Abuse

Мы сохраним этот файл под названием header.html в том же каталоге, что и другие шаблоны. Хотя многие сохраняют их в подкаталоге, называемом фрагменты .

Теперь мы хотим включить этот заголовок на другую страницу. Обратите внимание, что это не будет включать весь файл . Просто мы отметили как th:фрагмент . Давайте поместим этот заголовок над нашим приветственным сообщением:


    

Когда мы отрисовываем этот файл, HTML-страница будет выглядеть следующим образом:





    

Welcome to Stack Abuse Article

Welcome to world

Теперь есть три способа включить фрагменты: th:вставить , th:заменить и th:включить .

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

th:заменить заменит текущий тег фрагментом:


    

Это будет выглядеть как:





    

Welcome to Stack Abuse Article

Welcome to world

с идентификатором держателя теперь заменен фрагментом.

th:включить является предшественником тега th:заменить и работает таким же образом. Теперь это устарело.

Обработка ошибок и сообщений об ошибках

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

Для простоты мы будем использовать javax.проверки для проверки полей отправки формы:

@PostMapping("/article")
public String saveArticle(@ModelAttribute @Valid Article article, BindingResult bindingResult) {
    if (bindingResult.hasErrors()) {
        return "articleForm";
    }
    articleService.saveArticle(article);
    return "redirect:articles";
}

Это классический обработчик отправки формы. Мы упаковали информацию в статью объект и сохранили ее в базе данных. Однако на этот раз мы отметили статью как @Действительный и добавили проверку для экземпляра BindingResult .

Аннотация @Valid гарантирует, что полученная и упакованная информация об объекте соответствует проверкам, которые мы установили в Статье модели:

public class Article {
    @NotNull
    @Size(min = 2, max = 30)
    private String title;
    private String author;
    @NotNull
    @Size(min = 2, max = 1000)
    private String content;
    private String category;
    private String technology;
    private String area;
}

Если есть какие-либо нарушения этих правил, bindingresult.hasErrors() вернет true . И таким образом мы возвращаем форму обратно. вместо перенаправления пользователя на страницу /статьи .

Ошибки будут отображаться в форме в обозначенных местах, которые мы установили с помощью th:ошибки :

Name Error
Name Error

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

Вот как будет выглядеть отрисованная страница:

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

  • Вывод

    Эта статья предназначена как шлюз к Thymeleaf, очень популярному, современному движку шаблонов для приложений Java/Spring.

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