View 技术

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

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

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

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