对于最新的稳定版本,请使用 Spring Framework 7.0.6!spring-doc.cadn.net.cn

视图技术

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

百里叶

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

Thymeleaf与Spring WebFlux的集成由Thymeleaf项目管理。配置涉及一些bean声明,例如 SpringResourceTemplateResolver, SpringWebFluxTemplateEngine, 和 ThymeleafReactiveViewResolver. 有关更多详细信息,请参阅 Thymeleaf+Spring 和WebFlux集成的 公告spring-doc.cadn.net.cn

自由标记

Apache FreeMarker 是一个模板引擎,用于生成从 HTML 到电子邮件等各种类型的文本输出。Spring 框架内置了使用 Spring WebFlux 和 FreeMarker 模板的集成。spring-doc.cadn.net.cn

查看配置

以下示例展示了如何将FreeMarker配置为视图技术:spring-doc.cadn.net.cn

@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")
	}
}

您的模板需要存储在由FreeMarkerConfigurer指定的目录中,如前面的例子所示。根据前面的配置,如果您的控制器返回视图名称welcome,解析器将查找classpath:/templates/freemarker/welcome.ftl模板。spring-doc.cadn.net.cn

FreeMarker 配置

您可以直接将FreeMarker的“设置”和“共享变量”传递给由Spring管理的FreeMarker Configuration 对象,方法是设置FreeMarkerConfigurer bean的相应bean属性。freemarkerSettings 属性需要一个java.util.Properties 对象,而freemarkerVariables 属性需要一个java.util.Map。以下示例演示了如何使用FreeMarkerConfigurerspring-doc.cadn.net.cn

@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-doc.cadn.net.cn

表单处理

Spring 提供了一个标签库供 JSP 使用,其中包含一个 <spring:bind/> 元素。此元素主要用于让表单显示来自表单支持对象的值,并显示来自 web 或业务层中的 Validator 的验证失败结果。Spring 还支持在 FreeMarker 中使用相同的功能,并提供了额外的便利宏来生成表单输入元素。spring-doc.cadn.net.cn

绑定宏

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

Spring模板库中定义的一些宏被认为是内部的(私有的),但宏定义中没有这样的作用域,使得所有宏对调用代码和用户模板都是可见的。以下部分仅集中于你需要直接在模板中调用的宏。如果你想直接查看宏代码,文件名为spring.ftl,位于org.springframework.web.reactive.result.view.freemarker包中。spring-doc.cadn.net.cn

有关绑定支持的详细信息,请参阅简单绑定以了解Spring MVC。spring-doc.cadn.net.cn

表单宏

有关Spring对FreeMarker模板的表单宏支持的详细信息,请参阅Spring MVC文档的以下部分。spring-doc.cadn.net.cn

脚本视图

Spring框架内置了使用Spring WebFlux与任何可以在JSR-223 Java脚本引擎上运行的模板库集成的功能。 下表列出了我们在不同脚本引擎上测试过的模板库:spring-doc.cadn.net.cn

脚本库 脚本引擎

汉德尔斯spring-doc.cadn.net.cn

纳什角spring-doc.cadn.net.cn

Mustachespring-doc.cadn.net.cn

纳什角spring-doc.cadn.net.cn

反应spring-doc.cadn.net.cn

纳什角spring-doc.cadn.net.cn

EJSspring-doc.cadn.net.cn

纳什角spring-doc.cadn.net.cn

ERBspring-doc.cadn.net.cn

JRubyspring-doc.cadn.net.cn

字符串模板spring-doc.cadn.net.cn

Jythonspring-doc.cadn.net.cn

Kotlin 脚本模板spring-doc.cadn.net.cn

Kotlinspring-doc.cadn.net.cn

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

要求

你需要将脚本引擎添加到你的类路径中,具体细节因脚本引擎而异:spring-doc.cadn.net.cn

你需要拥有脚本模板库。对于Javascript,一种方法是通过WebJarsspring-doc.cadn.net.cn

脚本模板

您可以声明一个 ScriptTemplateConfigurer bean 来指定要使用的脚本引擎、要加载的脚本文件、调用什么函数来渲染模板等。 以下示例使用 Mustache 模板和 Nashorn JavaScript 引擎:spring-doc.cadn.net.cn

@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"
	}
}

The render 函数的调用参数如下:spring-doc.cadn.net.cn

Mustache.render() 与该签名原生兼容,因此您可以直接调用它。spring-doc.cadn.net.cn

如果你的模板技术需要一些定制化,你可以提供一个实现自定义渲染函数的脚本。例如,Handlebars 在使用模板之前需要编译模板,并且为了模拟一些在服务器端脚本引擎中不可用的浏览器功能,需要一个 polyfill。 以下示例展示了如何设置自定义渲染函数:spring-doc.cadn.net.cn

@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是在使用非线程安全的脚本引擎和未设计为支持并发的模板库(如Handlebars或在Nashorn上运行的React)时所必需的。在这种情况下,需要Java SE 8更新60,因为这个bug,但通常建议使用最近的Java SE补丁版本。

polyfill.js 定义了 Handlebars 正常运行所需的 window 对象, 如下所示的代码片段:spring-doc.cadn.net.cn

var window = {};

这个基本的render.js实现会在使用模板之前对其进行编译。一个生产环境的实现还应该存储和重用缓存的模板或预编译的模板。这可以在脚本侧完成,以及任何你需要的自定义(例如管理模板引擎配置)。 以下示例展示了如何编译模板:spring-doc.cadn.net.cn

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

查看Spring Framework的单元测试、Java资源,以获取更多配置示例。spring-doc.cadn.net.cn

JSON 和 XML

对于内容协商的目的,能够根据客户端请求的内容类型在使用HTML模板渲染模型和以其他格式(如JSON或XML)之间切换是有用的。为此,Spring WebFlux提供了HttpMessageWriterView,你可以使用它来插入任何可用的编解码器spring-web,例如Jackson2JsonEncoderJackson2SmileEncoderJaxb2XmlEncoderspring-doc.cadn.net.cn

与其它视图技术不同,HttpMessageWriterView 不需要 ViewResolver,而是作为默认视图进行配置。您可以配置一个或多个这样的默认视图,封装不同的 HttpMessageWriter 实例或 Encoder 实例。运行时将使用匹配请求内容类型的那一个。spring-doc.cadn.net.cn

在大多数情况下,模型包含多个属性。要确定要序列化的属性,你可以通过配置HttpMessageWriterView来指定要用于渲染的模型属性名称。如果模型只包含一个属性,则使用该属性。spring-doc.cadn.net.cn