Spring WebFlux 中视图技术的使用是可插拔的。您是否决定 使用 Thymeleaf、FreeMarker 或其他一些视图技术主要是一个问题 配置更改。本章介绍与 Spring 集成的视图技术 WebFlux 中。我们假设您已经熟悉视图分辨率

百里香叶

Thymeleaf 是一个现代服务器端 Java 模板引擎,强调自然 HTML 双击可以在浏览器中预览的模板,非常 有助于独立处理 UI 模板(例如,由设计师完成),而无需 正在运行的服务器。Thymeleaf 提供了一组广泛的功能,并且正在积极开发中 并维持。有关更完整的介绍,请参阅 Thymeleaf 项目主页。

Thymeleaf 与 Spring WebFlux 的集成由 Thymeleaf 项目管理。这 配置涉及一些 Bean 声明,例如 、 和 。有关详细信息,请参阅 Thymeleaf+Spring 和 WebFlux 集成公告SpringResourceTemplateResolverSpringWebFluxTemplateEngineThymeleafReactiveViewResolver

自由标记

Apache FreeMarker 是一个模板引擎,用于生成任何 从 HTML 到电子邮件等的文本输出类型。Spring 框架内置了 将 Spring WebFlux 与 FreeMarker 模板结合使用。

View 配置

以下示例演示如何将 FreeMarker 配置为视图技术:

  • Java

  • Kotlin

@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {

	@Override
	public void configureViewResolvers(ViewResolverRegistry registry) {
		registry.freeMarker();
	}

	// Configure FreeMarker...

	@Bean
	public FreeMarkerConfigurer freeMarkerConfigurer() {
		FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
		configurer.setTemplateLoaderPath("classpath:/templates/freemarker");
		return configurer;
	}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {

	override fun configureViewResolvers(registry: ViewResolverRegistry) {
		registry.freeMarker()
	}

	// Configure FreeMarker...

	@Bean
	fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply {
		setTemplateLoaderPath("classpath:/templates/freemarker")
	}
}

您的模板需要存储在 , 指定的目录中 如上例所示。给定上述配置,如果您的控制器 返回视图名称 ,解析程序将查找模板。FreeMarkerConfigurerwelcomeclasspath:/templates/freemarker/welcome.ftl

FreeMarker 配置

您可以通过设置适当的 bean 将 FreeMarker 的“设置”和“SharedVariables”直接传递给 FreeMarker 对象(由 Spring 管理) Bean 上的属性。该物业要求 一个对象,并且该属性需要 .以下示例演示如何使用:ConfigurationFreeMarkerConfigurerfreemarkerSettingsjava.util.PropertiesfreemarkerVariablesjava.util.MapFreeMarkerConfigurer

  • Java

  • Kotlin

@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;
	}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {

	// ...

	@Bean
	fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply {
		setTemplateLoaderPath("classpath:/templates")
		setFreemarkerVariables(mapOf("xml_escape" to XmlEscape()))
	}
}

请参阅 FreeMarker 文档,了解适用于 对象。Configuration

表单处理

Spring 提供了一个用于 JSP 的标签库,其中包含一个元素。此元素主要让表单显示来自 表单支持对象,并显示来自 Web 或业务层。Spring 还支持 FreeMarker 中的相同功能, 具有用于生成表单输入元素本身的额外便利宏。<spring:bind/>Validator

绑定宏

文件中维护了一组标准的宏 FreeMarker,因此它们始终可用于适当配置的应用程序。spring-webflux.jar

Spring 模板库中定义的某些宏被视为内部宏 (private),但宏定义中不存在此类范围,使所有宏都可见 调用代码和用户模板。以下各节仅重点介绍宏 您需要直接从模板中调用。如果要查看宏代码 直接调用该文件并位于包中。spring.ftlorg.springframework.web.reactive.result.view.freemarker

有关绑定支持的其他详细信息,请参阅 Spring MVC 的简单绑定

表单宏

有关 Spring 对 FreeMarker 模板的表单宏支持的详细信息,请参阅以下内容 Spring MVC 文档的部分。

脚本视图

Spring Framework 具有内置集成,可用于将 Spring WebFlux 与任何 可以在 JSR-223 Java 脚本引擎上运行的模板库。 下表显示了我们在不同脚本引擎上测试的模板库:

脚本库 脚本引擎

车把

纳斯霍恩

胡子

纳斯霍恩

反应

纳斯霍恩

EJS系列

纳斯霍恩

雇员再培训局

JRuby

字符串模板

Jython (英语)

Kotlin 脚本模板

科特林

集成任何其他脚本引擎的基本规则是它必须实现 and 接口。ScriptEngineInvocable

要求

您需要在类路径上安装脚本引擎,其详细信息因脚本引擎而异:

  • Nashorn JavaScript 引擎提供 Java 8+的。强烈建议使用可用的最新更新版本。

  • JRuby 应该被添加为 Ruby 支持的依赖项。

  • Jython 应添加为 Python 支持的依赖项。

  • org.jetbrains.kotlin:kotlin-script-util依赖项和包含一行的文件应添加以支持 Kotlin 脚本。有关详细信息,请参阅此示例META-INF/services/javax.script.ScriptEngineFactoryorg.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory

您需要有脚本模板库。对 JavaScript 执行此操作的一种方法是 通过 WebJars

脚本模板

你可以声明一个 bean 来指定要使用的脚本引擎, 要加载的脚本文件、要调用什么函数来呈现模板等。 以下示例使用 Mustache 模板和 Nashorn JavaScript 引擎:ScriptTemplateConfigurer

  • Java

  • Kotlin

@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;
	}
}
@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 renderingContextRenderingContext,用于访问应用程序上下文、区域设置、模板加载程序和 URL(自 5.0 起)

Mustache.render()与此签名本机兼容,因此您可以直接调用它。

如果您的模板技术需要一些自定义,您可以提供一个脚本 实现自定义渲染函数。例如,Handlerbars 在使用模板之前需要编译模板,并且需要 polyfill 才能模拟一些 浏览器功能在服务器端脚本引擎中不可用。 以下示例演示如何设置自定义呈现函数:

  • Java

  • Kotlin

@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;
	}
}
@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
	}
}
使用非线程安全时,需要将该属性设置为 脚本引擎的模板库不是为并发而设计的,例如 Handlebars 或 在 Nashorn 上运行的反应。在这种情况下,由于此错误,需要 Java SE 8 更新 60,但通常是 在任何情况下,都建议使用最新的 Java SE 补丁版本。sharedEnginefalse

polyfill.js仅定义 Handlebars 正常运行所需的对象, 如以下代码片段所示:window

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 提供了 ,您可以使用它从 中插入任何可用的编解码器,例如 、 、 或。HttpMessageWriterViewspring-webJackson2JsonEncoderJackson2SmileEncoderJaxb2XmlEncoder

与其他视图技术不同,它不需要,而是配置为默认视图。您可以 配置一个或多个此类默认视图,包装不同的实例 或实例。在运行时使用与请求的内容类型匹配的内容类型。HttpMessageWriterViewViewResolverHttpMessageWriterEncoder

在大多数情况下,一个模型包含多个属性。要确定要序列化的一个, 您可以使用要用于的模型属性的名称进行配置 渲染。如果模型仅包含一个属性,则使用该属性。HttpMessageWriterView