此版本仍在开发中,尚未被视为稳定版本。最新的稳定版本请使用 Spring Framework 6.1.13spring-doc.cn

此版本仍在开发中,尚未被视为稳定版本。最新的稳定版本请使用 Spring Framework 6.1.13spring-doc.cn

Spring WebFlux 中的视图渲染是可插拔的。无论您决定 使用 Lymeleaf、FreeMarker 或其他一些视图技术主要是 配置更改。本章介绍了与 Spring 集成的视图技术 WebFlux 的 Web Flux 中。spring-doc.cn

有关视图渲染的更多上下文,请参阅视图分辨率spring-doc.cn

Spring WebFlux 应用程序的视图位于内部信任边界内 的应用程序。视图可以访问应用程序上下文中的 bean,并且 因此,我们不建议在满足以下条件的应用程序中使用 Spring WebFlux 模板支持 模板可由外部源编辑,因为这可能会产生安全隐患。
Spring WebFlux 应用程序的视图位于内部信任边界内 的应用程序。视图可以访问应用程序上下文中的 bean,并且 因此,我们不建议在满足以下条件的应用程序中使用 Spring WebFlux 模板支持 模板可由外部源编辑,因为这可能会产生安全隐患。

百里香叶

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

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

自由标记

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

View 配置

以下示例显示了如何将 FreeMarker 配置为视图技术:spring-doc.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")
	}
}

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

FreeMarker 配置

你可以通过设置适当的 bean 将 FreeMarker 'Settings' 和 'SharedVariables' 直接传递给 FreeMarker 对象(由 Spring 管理)。 属性。该属性需要 对象,并且该属性需要 .以下示例演示如何使用 :ConfigurationFreeMarkerConfigurerfreemarkerSettingsjava.util.PropertiesfreemarkerVariablesjava.util.MapFreeMarkerConfigurerspring-doc.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 文档,了解设置和变量的详细信息,因为它们适用于这些设置 对象。Configurationspring-doc.cn

表单处理

Spring 提供了一个标记库,用于 JSP,其中包括一个元素。此元素主要允许表单显示来自 表单支持对象,并显示 Web 或业务层。Spring 在 FreeMarker 中也支持相同的功能, 具有用于生成表单输入元素本身的附加便捷宏。<spring:bind/>Validatorspring-doc.cn

Bind 宏

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

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

有关绑定支持的更多详细信息,请参阅 Spring MVC 的简单绑定spring-doc.cn

表单宏

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

脚本视图

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

脚本库 脚本引擎

车把spring-doc.cn

纳斯霍恩spring-doc.cn

胡子spring-doc.cn

纳斯霍恩spring-doc.cn

反应spring-doc.cn

纳斯霍恩spring-doc.cn

EJSspring-doc.cn

纳斯霍恩spring-doc.cn

雇员再培训局spring-doc.cn

JRubyspring-doc.cn

字符串模板spring-doc.cn

杰顿spring-doc.cn

Kotlin 脚本模板spring-doc.cn

Kotlinspring-doc.cn

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

要求

您需要在 Classpath 上具有脚本引擎,其详细信息因脚本引擎而异:spring-doc.cn

  • Nashorn JavaScript 引擎随 Java 8+ 的强烈建议使用可用的最新更新版本。spring-doc.cn

  • 应该将 JRuby 添加为 Ruby 支持的依赖项。spring-doc.cn

  • 应将 Jython 添加为 Python 支持的依赖项。spring-doc.cn

  • org.jetbrains.kotlin:kotlin-script-utildependency 并添加包含一行的文件以支持 Kotlin 脚本。有关更多详细信息,请参阅此示例META-INF/services/javax.script.ScriptEngineFactoryorg.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactoryspring-doc.cn

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

脚本模板

您可以声明一个 bean 来指定要使用的脚本引擎, 要加载的脚本文件、要调用的函数来渲染模板,等等。 以下示例使用 Mustache 模板和 Nashorn JavaScript 引擎:ScriptTemplateConfigurerspring-doc.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"
	}
}

使用以下参数调用该函数:renderspring-doc.cn

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

如果您的模板技术需要一些自定义,则可以提供一个脚本,该脚本 实现自定义 render 函数。例如,Handlerbars 需要在使用模板之前编译模板,并且需要一个 polyfill 来模拟一些 浏览器工具在服务器端脚本引擎中不可用。 以下示例显示如何设置自定义 render 函数:spring-doc.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
	}
}
使用非线程安全时,需要将属性设置为 具有非并发性模板库的脚本引擎,例如 Handlebars 或 React 在 Nashorn 上运行。在这种情况下,由于此错误,需要 Java SE 8 Update 60,但通常是 建议在任何情况下使用最新的 Java SE 补丁版本。sharedEnginefalse

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

var window = {};

此基本实现在使用模板之前对其进行编译。A 生产 ready 实现还应存储和重用缓存的模板或预编译的模板。 这可以在脚本端完成,也可以完成您需要的任何自定义(管理 模板引擎配置)。 以下示例显示了如何编译模板:render.jsspring-doc.cn

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

查看 Spring Framework 单元测试、Java资源。 了解更多配置示例。spring-doc.cn

脚本库 脚本引擎

车把spring-doc.cn

纳斯霍恩spring-doc.cn

胡子spring-doc.cn

纳斯霍恩spring-doc.cn

反应spring-doc.cn

纳斯霍恩spring-doc.cn

EJSspring-doc.cn

纳斯霍恩spring-doc.cn

雇员再培训局spring-doc.cn

JRubyspring-doc.cn

字符串模板spring-doc.cn

杰顿spring-doc.cn

Kotlin 脚本模板spring-doc.cn

Kotlinspring-doc.cn

集成任何其他脚本引擎的基本规则是它必须实现 and 接口。ScriptEngineInvocable
使用非线程安全时,需要将属性设置为 具有非并发性模板库的脚本引擎,例如 Handlebars 或 React 在 Nashorn 上运行。在这种情况下,由于此错误,需要 Java SE 8 Update 60,但通常是 建议在任何情况下使用最新的 Java SE 补丁版本。sharedEnginefalse

HTML 片段

HTMXHotwire Turbo 强调 HTML over-the-wire 方法,其中客户端以 HTML 而不是 JSON 格式接收服务器更新。 这允许 SPA(单页应用程序)的好处,而无需编写太多甚至 任何 JavaScript。如需良好的概述和了解更多信息,请访问他们各自的 网站。spring-doc.cn

在 Spring WebFlux 中,视图渲染通常涉及指定一个视图和一个模型。 但是,在 HTML-over-the-wire 中,一个常见的功能是发送多个 HTML 片段,这些片段 浏览器可用于更新页面的不同部分。为此,控制器方法 可以返回 。例如:Collection<Fragment>spring-doc.cn

@GetMapping
List<Fragment> handle() {
	return List.of(Fragment.create("posts"), Fragment.create("comments"));
}
@GetMapping
fun handle(): List<Fragment> {
	return listOf(Fragment.create("posts"), Fragment.create("comments"))
}

也可以通过返回 dedicated type 来完成相同的操作:FragmentsRenderingspring-doc.cn

@GetMapping
FragmentsRendering handle() {
	return FragmentsRendering.with("posts").fragment("comments").build();
}
@GetMapping
fun handle(): FragmentsRendering {
	return FragmentsRendering.with("posts").fragment("comments").build()
}

每个 fragment 都可以有一个独立的模型,并且该模型从 请求的共享模型。spring-doc.cn

HTMX 和 Hotwire Turbo 支持通过 SSE(服务器发送的事件)流式传输更新。 控制器可以使用 、 或任何其他 反应式生产者,可通过 . 也可以在没有包装器的情况下直接返回。FragmentsRenderingFlux<Fragment>PublisherReactiveAdapterRegistryFlux<Fragment>FragmentsRenderingspring-doc.cn

JSON 和 XML

出于 Content Negotiation 目的,能够交替使用 使用 HTML 模板或其他格式(如 JSON 或 XML)渲染模型之间, 取决于客户端请求的内容类型。为了支持这样做,Spring WebFlux 提供 ,您可以使用它从 中插入任何可用的编解码器,例如 、 、 或。HttpMessageWriterViewspring-webJackson2JsonEncoderJackson2SmileEncoderJaxb2XmlEncoderspring-doc.cn

与其他视图技术不同,它不需要 a,而是配置为默认视图。您可以 配置一个或多个这样的默认视图,包装不同的实例 或 instances 的 S 。在运行时使用与请求的内容类型匹配的 URL。HttpMessageWriterViewViewResolverHttpMessageWriterEncoderspring-doc.cn

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