Java: Веб-технологии
Теория: Шаблонизатор
В этом уроке мы познакомимся с шаблонизаторами.
Зачем нужны шаблонизаторы
Javalin и другие подобные фреймворки позволяют создавать полноценные сайты без дополнительных инструментов. Рабочий сайт должен просто возвращать ответ с HTML-кодом, который браузер отобразит как страницу:
Здесь мы видим упрощенный пример, в котором мы возвращаем только заголовок H1.
В реальных приложениях возвращаемый HTML состоит из сотен и тысяч строк. Работать с такими объемами стандартным способом очень сложно. Вот лишь некоторые проблемы, с которыми мы столкнемся:
- Такой код сложно формировать, редактировать и поддерживать
- В таком коде очень легко допустить ошибку и очень сложно ее обнаружить
- В таком коде будут возникать проблемы с одинарными или двойными кавычками, придется их экранировать и постоянно следить за этим
Для решения этой проблемы используются шаблонизаторы. Это библиотеки, которые позволяют формировать HTML в отдельных файлах с подсветкой и удобной подстановкой данных. Другими словами, мы получаем не HTML внутри кода, а код внутри HTML.
В Java-мире есть несколько разных шаблонизаторов. Для этого курса мы выбрали jte (Java Template Engine), потому что он официально поддерживается в Javalin.
Посмотрим, как выглядит HTML c jte:
Как начать работать с JTE
Чтобы начать работу с jte, нужно добавить в зависимости две строчки:
Пакет javalin-rendering добавляет в Javalin поддержку нескольких популярных шаблонизаторов, в том числе jte. В конфигурации приложения нужно указать, что мы хотим использовать jte в качестве шаблонизатора в нашем приложении:
Шаблоны JTE с HTML хранятся в директории src/main/jte и имеют расширение jte. Чтобы попрактиковаться, добавим первый шаблон для главной страницы сайта. Для этого выполним два действия:
-
Создадим шаблон src/main/jte/index.jte со следующим содержимым:
-
Укажем обработчику главной страницы использовать этот шаблон:
Обратите внимание на метод ctx.render() в коде выше. Он выполняет рендеринг указанного шаблона и добавляет результат в HTTP-ответ.
Путь до шаблона указывается относительно директории src/main/jte:
Сами шаблоны могут располагаться и на более глубоком уровне. Это становится важно, когда количество шаблонов увеличивается.
Шаблонизатор не задает правила именования и внутренней структуры шаблонов. Но работать без правил слишком сложно, поэтому со временем мы самостоятельно выработаем правила и будем их придерживаться.
В директории src/main/jte помимо самих шаблонов может быть расположен файл .jteroot. Это просто пустой файл, который указывает JTE, где находится корневая директория с шаблонами. Хотя в Javalin наличие этого файла не является обязательным, так как шаблонизатор уже заранее сконфигурирован фреймворком для поиска шаблонов в директории src/main/jte, мы рекомендуем его создавать. Этот файл помогает IntelliJ IDEA точно определять расположение шаблонов и корректно подсвечивать синтаксис, что в свою очередь упрощает работу с проектом.
Как работает отображение данных
Как правило, HTML внутри шаблонов формируется на основе данных, которые мы хотим вывести. Например, чтобы вывести информацию о курсе на странице /courses/{id}, мы передаем объект этого курса в шаблон и формируем HTML на основе его содержимого.
Попробуем проделать этот путь. Создадим класс для курса с тремя полями — идентификатором, названием и описанием:
По идее, обработчик маршрута /courses/{id} получает курс из базы данных и передает его в шаблон. Для этого создадим дата-класс:
Осталось написать обработчик и посмотреть, как все это работает в связке:
Рассмотрим, по какому алгоритму обработчики обычно работают с шаблонами:
- Сначала они извлекают все необходимые данные
- Затем они создают объект дата-класса и заполняют его этими данными
- В итоге они передают этот объект в шаблон в виде Map, созданного при помощи статического метода
model(), который предоставляет Javalin
Остался последний шаг — вывести данные курса в шаблоне. Для этого в шаблонах используется специальный синтаксис. Через него мы указываем, какой дата-класс мы используем и под каким именем хотим передать его объект в шаблон. В нашем случае это объект класса CoursePage, переданный под именем page:
В первых двух строчках шаблона мы используем директивы — специальные конструкции, которые начинаются со знака @:
- Директива
@importаналогична импорту в Java - Директива
@paramуказывает, какие данные нужно использовать внутри Map, переданного в шаблон. Доступ к данным внутри шаблона идет через это имя
Дальше мы видим подстановку данных внутрь HTML. Этот способ называется интерполяцией. Он работает через указание Java-кода внутри структуры ${}.
Какие управляющие конструкции используются в jte
Кроме обычного вывода значений, в шаблонах часто используются условные конструкции и циклы. С их помощью показываются списки, прячутся или показываются определенные блоки и так далее.
Подробнее обо всех этих конструкциях можно прочитать в официальной документации. А здесь мы разберем пример на базе маршрута /courses, по которому выводится список курсов с описанием и ссылками на курсы:
-
Начнем с дата-класса. Кроме курсов, добавим еще и заголовок для разнообразия:
-
Перейдем к обработчику:
-
В конце переходим к шаблону:
Логика вывода здесь такая:
- Если список курсов пустой, то выводится соответствующее сообщение
- Если курсы в списке есть, то на основе этого списка формируются HTML-блоки с информацией о курсе и ссылкой на его страницу
Этих конструкций хватит для решения большинства стандартных задач, потому что внутри них можно использовать любой Java-код. Единственное, что нужно не забывать — это импортировать используемые классы через директиву @import.



