Написание простых приложений на http4k

Написание простых приложений на http4k #

Документация #

Шаблон приложения #

Скачайте архив, с исходным кодом проекта по ссылке. Данный проект основан на базовом шаблоне проекта, в который были внесены изменения.

Стартовой функцией приложения является функция main, расположенная в файле ru/yarsu/WebApplication.kt. Эта информация внесена в конфигурационный файл системы сборки Gradle.

В пакете ru.yarsu.web расположен код приложения, выполняющий обработку HTTP-запросов.

Маршрутизатор HTTP-запросов приложения описывается в файле ru/yarsu/web/Router.kt и записывается в переменную router.

Классы, реализующие HTTP-обработчики, помещены в пакет ru.yarsu.web.handlers. Для каждого из двух обработчиков создан отдельный класс в отдельном файле.

В стартовой функции main динамические маршруты приложения объединяются с обработчиком HTTP-запросов за статическими (неизменяемыми) данными. Статические данные берутся из ресурсов приложения по пути ресурсов /ru/yarsu/public. На момент компиляции приложения они расположены в каталоге проекта src/main/resources/ru/yarsu/public.

В каталоге со статическими данными добавлены CSS и JS-файлы библиотеки Bootstrap. Ввиду конфигурации подсистемы раздачи статических файлов они будут доступны по частичному абсолютному пути /css/bootstrap.min.css и /js/bootstrap.bundle.min.js.

Использование шаблонов Pebble #

В рамках библиотеки http4k предоставляется унифицированная прослойка для работы с разными шаблонизаторами. В рамках данной прослойки выделены два элемента — компонент для настройки параметров шаблонизатора и классы-модели.

Настройка шаблонизатора #

Первые компоненты позволяют получить доступ к шаблонизатору и настроить политику кеширования. В рамках обработчика ru.yarsu.web.handlers.PebbleHandler данный объект создаётся следующим образом:

val renderer = PebbleTemplates().CachingClasspath()

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

  • Кеширование шаблонов из файловой системы, Caching().
  • Прямая загрузка шаблонов из файловой системы без кеширования, HotReload().

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

Использование моделей #

Вторым компонентом системы являются модели. Модели — это классы, реализующие интерфейс org.http4k.template.ViewModel. Данный интерфейс не накладывает никакие ограничения на класс, но предоставляет функцию template(), которая по каноническому названию класса формирует путь к шаблону, который будет использован при её отображении.

В примере создана модель ru.yarsu.web.models.PebbleVM. Для данной модели путём для соответствующего ей шаблона является /ru/yarsu/web/models/PebbleVM.peb. Данный путь будет разрешён согласно конфигурации объекта-шаблонизатора.

При вызове шаблонизатора renderer(viewModel) будет вычислен путь к шаблону и ему в качестве данных будет передан объект модели. Модель будет доступна внутри шаблона по названию model.

Пути к другим моделям #

При использовании техники наследования шаблонов или при включении шаблонов необходимо использовать относительные пути с указанием текущего каталога. Например для подключения файла-раскладки Layout.peb, находящегося рядом с текущим файлом, с помощью тега extends необходимо использовать путь ./Layout.peb, а не Layout.peb.

Задача № 1. Создание обработчика корневого маршрута #

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

Ниже представлен подход к решению задачи.

  1. Сформируйте набор изображений треугольников в каталоге src/main/resources/ru/yarsu/public/images. Изображения можно сформировать самостоятельно или взять с ресурсов сети интернет. В последнем случае учитывайте условия использования чужого изображения. Данные изображения будут доступны по частичному абсолютному пути /images/isosceles.png.
  2. Создайте обработчик HTTP-запроса, который будет на текущий момент отвечать пустой строкой.
    1. Создайте класс ru.yarsu.web.handlers.HomeHandler.
    2. Унаследуйте данный класс от функционального типа org.http4k.core.HttpHandler.
    3. Внутри реализуемой функции ivoke создайте ответ с кодом статуса OK, содержащий строку Стартовая страница.
  3. Свяжите созданный обработчик с маршрутом /.
    1. Внутри маршрутизатора добавьте связь маршрута / с объектом созданного на предыдущем шаге класса HomeHandler.
    2. Перезапустите приложение и обратитесь к нему по корневому пути. Убедитесь, что в браузере отображается слово Стартовая страница.
  4. Реализуйте Pebble-шаблон HTML-документа с необходимым содержимым. Разместите содержимое в файле src/main/resources/ru/yarsu/web/models/HomePageVM.peb.
    1. В качестве базы для реализации возьмите содержимое файла PebbleVM.peb.
    2. Добавьте необходимое текстовое и мультимедиа содержимое внутри данного файла.
  5. Создайте модель для связи шаблонизатора и данного файла.
    1. Создайте пустой класс ru.yarsu.web.models.HomePageVM.
    2. Унаследуйте данный класс от интерфейса org.http4k.template.ViewModel.
  6. Внутри HTTP-обработчика стартовой страницы используйте шаблонизатор, класс-модель и шаблон для отображения содержимого страницы.
    1. Внутри класса ru.yarsu.web.handlers.HomeHandler создайте Pebble-шаблонизатор средствами библиотеки http4k. Выберите режим кеширующей работы с данными из ресурсов.
    2. Создайте строку на основании шаблона. Примените шаблонизатор к объекту класса ru.yarsu.web.models.HomePageVM.
    3. Выведите созданную строку с текстом HTML-документа в качестве ответа на запрос вместо строки Стартовая страница.
    4. Перезапустите приложение и обратитесь к нему по корневому пути. Убедитесь, что в браузере корректно отображается нужная страница.

Задача № 2. Создание одного объекта-шаблонизатора Pebble #

При создании обработчика HTTP-запроса был создан объект для настройки шаблонизатора внутри его. Вроде бы написали всего одну строчку, но в каждом следующем обработчике придётся дописывать данную строчку. Другая проблема — если в будущем потребуется внести настройки в шаблонизатор, то придётся вносить это изменение во все обработчики.

Логичным решением является уменьшение дублирования логики между HTTP-обработчиком путём передачи созданного объекта в качестве параметра конструктора обработчика. В результате объём кода HTTP-обработчиков уменьшится, появится возможность выполнения настройки в едином месте.

Решите проблему дублирования при создании объекта-шаблонизатора. Данный объект должен создаваться в стартовой функции и затем передаваться через маршрутизатор в конкретные обработчики HTTP-запросов.

Ниже представлен подход к решению задачи.

  1. Создайте функцию по формированию объекта-шаблонизатора.
    1. Создайте файл ru/yarsu/web/TemplateRenderer.kt.
    2. Создайте в файле функцию, которая возвращает объект типа org.http4k.template.TemplateRenderer. Данная функция должна принимать в качестве аргумента логический тип.
    3. В зависимости от значения переданного аргумента функция должна возвратить либо кеширующий шаблонизатор, либо шаблонизатор с прямой загрузкой данных с жёсткого диска.
  2. Вызовите данную функцию в стартовом файле приложения, результат вызова функции поместите в переменную. При разработке приложения можете использовать вариант шаблонизатора, загружающий данные с жёсткого диска.
  3. Замените переменную для хранения маршрутизатора функцией, которая принимает в качестве аргумента объект шаблонизатора и возвращающей объект типа org.http4k.routing.RoutingHttpHandler.
    1. В файле ru/yarsu/web/Router.kt замените переменную router на функцию router.
    2. Добавьте данной функции необходимый аргумент — ссылку на объект шаблонизатора.
    3. Убедитесь, что функция возвращает созданный маршрутизируемый обработчик HTTP-запросов.
    4. Вызовите данную функцию в старотовом файле приложения вместо обращения к переменной, передайте ей в качестве аргумента ссылку на созданный на предыдущем шаге объект шаблонизатора.
  4. Передайте объект шаблонизатор во все обработчики HTTP-запросов и замените им создание собственных обработчиков. Для каждого HTTP-обработчика:
    1. Добавьте в конструктор передачу ссылки на объект шаблонизатора. Данную ссылку необходимо сохранить в приватном неизменяемом поле класса. Объект необходим только внутри обработчика, поэтому поле не должно быть доступно вне объектов класса.
    2. Удалите создание новых объектов в существующих HTTP-обработчиках.
    3. Перезапустите приложение и убедитесь, что приложение функционирует корректно.

Задача № 3. Реализация навигационной панели и общей раскладки #

В созданных Pebble-шаблонах также присутствует дублирование:

  • В логике подключения ресурсов.
  • В базовой раскладке. Она только усилится при добавлении навигационной панели.

В рамках данного шага вынесите общую логику в отдельный файл-раскладку и измените существующие Pebble-шаблоны на её использование.

  1. Создайте файл-раскладку src/main/resources/web/models/partials/Layout.peb.
    1. Перенесите в данный файл общее содержимое.
    2. Определите блоки для расширения: заголовок страницы и содержимое страницы.
  2. Измените каждый из существующих Pebble-шаблонов на использование данной раскладки.
    1. Корректно укажите путь для расширения файла-раскладки. Относительный путь будет выглядеть как ./partials/Layout.peb.
    2. Заполните блоки расширения соответствующей информацией.
  3. Перезапустите приложение и удостоверьтесь, что приложение успешно отображает обе страницы, использующие Pebble-шаблоны.
  4. Добавьте навигационную панель, позволяющую переходить между всеми разделами сайта.
    1. В файл-раскладке разместите навигационную панель, включающую ссылку к корневому маршруту и к маршруту по отображению страницы-демонстратора работы с Pebble-шаблонами.
  5. Перезапустите приложение и удостоверьтесь, что приложение позволяет переходить между данными страницами без ручного редактирования адресной строки в браузере.

Задача № 4. Отображение списка треугольников #

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

Маршрут для отображения страницы — /triangle/.

Ниже представлен подход к решению задачи.

  1. Возьмите код для чтения списка треугольников из предыдущих практик. Расположите класс для описания треугольника в пакете ru.yarsu.domain.
  2. В стартовой функции приложения реализуйте считывание списка треугольников из файла.
  3. Создайте модель для отображения списка треугольников. В классе ru.yarsu.web.handlers.TrangleListVM добавьте поле triangles для хранения списка треугольников.
  4. Создайте Pebble-шаблон для отображения списка треугольников. Внутри шаблона используйте model.triangles для доступа к списку треугольников.
  5. Создайте обработчик HTTP-запроса для отображения списка треугольников.
    1. Данный обработчик должен принимать в качестве аргументов список треугольников и объект-шаблонизатора.
    2. На основании переданных данных обработчик должен формировать HTML-документ и возвращать его в качестве тела ответа.
  6. Свяжите созданный обработчик с путём /triangle в маршрутизаторе.
    1. Добавьте функции по созданию маршрутизатора аргумент — список треугольников.
    2. Внутри функции используйте данный аргумент для создания объекта HTTP-обработчика для класса, описанного в предыдущем шаге.
    3. Свяжите созданный объект с GET-запросом по пути /triangle.
    4. В стартовой функции передайте функции по созданию маршрутизатора объект со списком треугольников.
  7. Добавьте в общую навигационную панель путь к странице со списком треугольников.
  8. Перезапустите приложение. Убедитесь, что пользователь со стартовой страницы может перейти на страницу со списком треугольников и назад, к стартовой странице.

© A. M. Васильев, 2024, CC BY-SA 4.0, andrey@crafted.su