查看技术

在Spring WebFlux中使用视图技术是可插拔的。无论您决定使用Thymeleaf、FreeMarker还是其他视图技术,主要是一个配置更改的问题。本章介绍了与Spring WebFlux集成的视图技术。我们假设您已经熟悉视图解析

Thymeleaf

Thymeleaf是一种现代的服务器端Java模板引擎,强调自然的HTML模板,可以通过双击在浏览器中预览,这对独立工作于UI模板(例如设计师)非常有帮助,而无需运行服务器。Thymeleaf提供了丰富的功能,并且在积极开发和维护中。有关更完整的介绍,请参阅Thymeleaf项目主页。

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

FreeMarker

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

视图配置

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

  • Java

  • Kotlin

@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;
	}
}
@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配置

FreeMarkerConfigurer bean上设置适当的bean属性,直接将FreeMarker的“Settings”和“SharedVariables”传递给FreeMarker Configuration对象(由Spring管理)。以下示例显示了如何使用 FreeMarkerConfigurer

  • 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()))
	}
}
Configuration对象。

表单处理

<spring:bind/>元素等内容。此元素主要允许表单显示来自表单后端对象的值,并显示来自Web或业务层中 Validator的验证失败结果。Spring还支持在FreeMarker中具有相同功能的支持,还提供了用于生成表单输入元素本身的额外便利宏。

绑定宏

spring-webflux.jar文件中维护,因此它们始终对适当配置的应用程序可用。

spring.ftl,位于 org.springframework.web.reactive.result.view.freemarker包中。

简单绑定。

脚本视图

Spring Framework内置了一个集成,可以使用任何可以在JSR-223 Java脚本引擎之上运行的模板库与Spring WebFlux一起使用。以下表格显示了我们在不同脚本引擎上测试过的模板库:

脚本库 脚本引擎

Handlebars

Nashorn

Mustache

Nashorn

React

Nashorn

EJS

Nashorn

ERB

JRuby

字符串模板

Jython

Kotlin脚本模板

Kotlin

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

要求

您需要在类路径上拥有脚本引擎,具体细节因脚本引擎而异:

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

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

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

  • 为了支持Kotlin脚本,应添加org.jetbrains.kotlin:kotlin-script-util依赖项,并添加一个包含org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory行的META-INF/services/javax.script.ScriptEngineFactory文件。有关更多详细信息,请参见此示例

您需要拥有脚本模板库。为JavaScript做到这一点的一种方法是通过WebJars

脚本模板

您可以声明一个ScriptTemplateConfigurer bean来指定要使用的脚本引擎、要加载的脚本文件、要调用以渲染模板等。以下示例使用Mustache模板和Nashorn JavaScript引擎:

  • 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 renderingContext:提供对应用程序上下文、区域设置、模板加载器和URL(自5.0起)的访问权限的RenderingContext

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

如果您的模板技术需要一些定制,您可以提供一个实现自定义渲染函数的脚本。例如,Handlebars需要在使用模板之前编译模板,并且需要一个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
	}
}
sharedEngine属性设置为false是在使用非线程安全的脚本引擎与不适用于并发的模板库(如运行在Nashorn上的Handlebars或React)时所必需的。在这种情况下,由于此bug,需要Java SE 8更新60,但通常建议在任何情况下使用最新的Java SE补丁版本。

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提供了HttpMessageWriterView,您可以使用它来插入来自spring-web中可用的任何编解码器,例如Jackson2JsonEncoderJackson2SmileEncoderJaxb2XmlEncoder

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

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