Thymeleaf

Thymeleaf - это современный шаблонизатор Java на стороне сервера, который делает упор на естественные HTML-шаблоны, которые можно предварительно просмотреть в браузере двойным щелчком мыши, что очень удобно при самостоятельной работе над шаблонами пользовательского интерфейса (например, дизайнеру) без необходимости наличия работающего сервера. Thymeleaf предлагает обширный набор функций, активно развивается и поддерживается. Более полную вводную информацию можно найти на домашней странице проекта Thymeleaf.

Интеграция Thymeleaf с Spring WebFlux управляется проектом Thymeleaf. Конфигурация предусматривает несколько объявлений бинов, таких как SpringResourceTemplateResolver, SpringWebFluxTemplateEngine и ThymeleafReactiveViewResolver. Для получения более подробной информации см. раздел "Thymeleaf+Spring" и анонс интеграции с WebFlux.

FreeMarker

Apache FreeMarker - это шаблонизатор для генерации любого вида текстового вывода от HTML до электронной почты и др. Spring Framework имеет встроенную интеграцию для использования Spring WebFlux с шаблонами из FreeMarker.

Конфигурация представления

В следующем примере показано, как можно сконфигурировать FreeMarker в качестве технологии представления:

Java
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.freeMarker();
}
// Конфигурируем FreeMarker...
@Bean
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath("classpath:/templates/freemarker");
return configurer;
}
}
Kotlin
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
registry.freeMarker()
}
// Конфигурируем FreeMarker...
@Bean
fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply {
setTemplateLoaderPath("classpath:/templates/freemarker")
}
}

Ваши шаблоны должны храниться в директории, указанной FreeMarkerConfigurer, как это показано в предыдущем примере. Учитывая предыдущую конфигурацию, если контроллер возвращает имя представления welcome, преобразователь ищет шаблон classpath:/templates/freemarker/welcome.ftl.

Конфигурация FreeMarker

Можно передать "Settings" и "SharedVariable" обработчика FreeMarker непосредственно в объект Configuration обработчика FreeMarker (который управляется Spring), установив соответствующие свойства бина в FreeMarkerConfigurer. Для свойства freemarkerSettings требуется объект java.util.Properties, а для свойства freemarkerVariables - java.util.Map. В следующем примере показано, как использовать FreeMarkerConfigurer:

Java
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
// ...
@Bean
public FreeMarkerConfigurer freeMarkerConfigurer() {
Map<String, Object> variables = new HashMap<>();
variables.put("xml_escape", new XmlEscape());
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath("classpath:/templates");
configurer.setFreemarkerVariables(variables);
return configurer;
}
}
Kotlin
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
// ...
@Bean
fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply {
setTemplateLoaderPath("classpath:/templates")
setFreemarkerVariables(mapOf("xml_escape" to XmlEscape()))
}
}

Подробности о настройках и переменных, применимых к объекту Configuration, см. в документации по FreeMarker.

Обработка форм

Spring предусматривает библиотеку тегов для использования в JSP, которая содержит, среди прочего, элемент <spring:bind/>. Этот элемент в первую очередь позволяет формам выводить на экран значения из базовых объектов формы и отображать результаты неудачных проверок из Validator на веб-уровне или бизнес-уровне. Spring также имеет поддержку той же функциональности во FreeMarker, с дополнительными удобными макросами для генерации самих элементов ввода формы.

Макросы привязки

Средства поддержки стандартного набора макросов находятся в файле spring-webflux.jar для FreeMarker, поэтому они всегда доступны для соответствующим образом настроенного приложения.

Некоторые макросы, определенные в библиотеках шаблонизации в Spring, считаются внутренними (приватными), но в определениях макросов такого ограничения нет, что делает все макросы видимыми для вызывающего кода и пользовательских шаблонов. Следующие разделы посвящены только тем макросам, которые необходимо вызывать непосредственно из шаблонов. Если вам нужно просмотреть код макроса напрямую, файл называется spring.ftl и находится в пакете org.springframework.web.reactive.result.view.freemarker.

Макросы формы

Для получения подробной информации о средствах поддержки макросов форм для шаблонов FreeMarker в Spring обратитесь к следующим разделам документации Spring MVC.

  • Макросы ввода

  • Поля ввода

  • Поля выбора

  • HTML-экранирование

Скриптовые представления

Spring Framework имеет встроенную интеграцию для использования Spring WebFlux с любой библиотекой шаблонизации, которая может выполняться поверх механизма выполнения скриптов по спецификации JSR-223 в Java. В следующей таблице представлены библиотеки шаблонов, которые мы тестировали на различных механизмах выполнения скриптов:

Библиотека скриптов Механизм выполнения скриптов

Handlebars

Nashorn

Mustache

Nashorn

React

Nashorn

EJS

Nashorn

ERB

JRuby

Шаблоны строк

Jython

Шаблонизация скриптов в Kotlin

Kotlin

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

Требования

Необходимо обеспечить наличие механизма выполнения скриптов в своем classpath, детали которого зависят от механизма выполнения скриптов:

  • Механизм обработки JavaScript под названием Nashorn поставляется вместе с Java 8+. Настоятельно рекомендуется использовать последний доступный выпуск обновления.

  • JRuby необходимо добавить в качестве зависимости для обеспечения поддержки языка Ruby.

  • Jython необходимо добавить в качестве зависимости для обеспечения поддержки языка Python.

  • Для обеспечения поддержки скриптов Kotlin следует добавить зависимость org.jetbrains.kotlin:kotlin-script-util и файл META-INF/services/javax.script.ScriptEngineFactory, содержащий строку org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory. Более подробную информацию см. в этом примере.

Вам необходимо добавить библиотеку шаблонизации скриптов. Один из способов сделать это в случае с JavaScript – WebJars.

Шаблоны скриптов

Вы можете объявить бин ScriptTemplateConfigurer, чтобы задать, какой механизм выполнения скриптов использовать, какие файлы скриптов загружать, какую функцию вызывать для визуализации шаблонов и так далее. В следующем примере используются шаблоны Mustache и механизм обработки скриптов JavaScript под названием Nashorn:

Java
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.scriptTemplate();
}
@Bean
public ScriptTemplateConfigurer configurer() {
ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
configurer.setEngineName("nashorn");
configurer.setScripts("mustache.js");
configurer.setRenderObject("Mustache");
configurer.setRenderFunction("render");
return configurer;
}
}
Kotlin
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
registry.scriptTemplate()
}
@Bean
fun configurer() = ScriptTemplateConfigurer().apply {
engineName = "nashorn"
setScripts("mustache.js")
renderObject = "Mustache"
renderFunction = "render"
}
}

Функция render вызывается со следующими параметрами:

  • String template: Содержание шаблона

  • Map model: Модель представления

  • RenderingContext renderingContext: RenderingContext, который предоставляет доступ к контексту приложения, региональным настройкам, загрузчику шаблонов и URL-адресу (начиная с версии 5.0).

Mustache.render() изначально совместим с этой сигнатурой, поэтому можно вызывать его напрямую.

Если ваша технология шаблонизации требует некоторой настройки, то можно передать скрипт, который реализует кастомную функцию визуализации. Например, Handlerbars требует компиляции шаблонов перед их использованием и требует полизаполнение для эмуляции некоторых возможностей браузера, которые недоступны в механизме выполнения скриптов на стороне сервера. В следующем примере показано, как установить кастомную функцию визуализации:

Java
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.scriptTemplate();
}
@Bean
public ScriptTemplateConfigurer configurer() {
ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
configurer.setEngineName("nashorn");
configurer.setScripts("polyfill.js", "handlebars.js", "render.js");
configurer.setRenderFunction("render");
configurer.setSharedEngine(false);
return configurer;
}
}
Kotlin
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
registry.scriptTemplate()
}
@Bean
fun configurer() = ScriptTemplateConfigurer().apply {
engineName = "nashorn"
setScripts("polyfill.js", "handlebars.js", "render.js")
renderFunction = "render"
isSharedEngine = false
}
}
Установка свойства sharedEngine в false необходима при использовании небезопасных для потоков механизмов выполнения скриптов с библиотеками шаблонов, не рассчитанными на параллелизм, например, Handlebars или React, работающие на Nashorn. В этом случае требуется обновление Java SE 8 update 60 из-за этого бага, но обычно в любом случае рекомендуется использовать последний выпуск патча Java SE.

polyfill.js определяет лишь объектwindow, необходимый Handlebars для правильной работы, как это показано в следующем фрагменте:

var window = {};

Эта базовая реализация render.js компилирует шаблон перед его использованием. Реализация, пригодная к производственному использованию, также должна хранить любые повторно используемые кэшированные шаблоны или предварительно скомпилированные шаблоны. Это можно сделать на стороне скрипта, а также при любых необходимых вам настройках (например, управляя конфигурацией шаблонизатора). В следующем примере показано, как скомпилировать шаблон:

function render(template, model) {
var compiledTemplate = Handlebars.compile(template);
return compiledTemplate(model);
}

Ознакомьтесь с модульными тестами Spring Framework, Java и ресурсами, чтобы просмотреть больше примеров конфигурации.

JSON и XML

Из соображений согласования содержимого полезно иметь возможность чередовать отображение модели с шаблоном в формате HTML или в других форматах (таких как JSON или XML), в зависимости от типа содержимого, запрашиваемого клиентом. Для поддержки этой функции Spring WebFlux предусматривает HttpMessageWriterView, который можно использовать для подключения любого из доступных кодеков из spring-web, таких как Jackson2JsonEncoder, Jackson2SmileEncoder или Jaxb2XmlEncoder.

В отличие от других технологий представления, HttpMessageWriterView не требует ViewResolver, а конфигурируется как представление по умолчанию. Можно сконфигурировать одно или несколько таких представлений по умолчанию, обернув ими различные экземпляры HttpMessageWriter или экземпляры Encoder. Во время выполнения используется то, которое соответствует запрашиваемому типу содержимого.

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