此版本仍在开发中,尚未被视为稳定版本。最新的稳定版本请使用 Spring Framework 6.1.13! |
此版本仍在开发中,尚未被视为稳定版本。最新的稳定版本请使用 Spring Framework 6.1.13! |
Spring WebFlux 中的视图渲染是可插拔的。无论您决定 使用 Lymeleaf、FreeMarker 或其他一些视图技术主要是 配置更改。本章介绍了与 Spring 集成的视图技术 WebFlux 的 Web Flux 中。
有关视图渲染的更多上下文,请参阅视图分辨率。
Spring WebFlux 应用程序的视图位于内部信任边界内 的应用程序。视图可以访问应用程序上下文中的 bean,并且 因此,我们不建议在满足以下条件的应用程序中使用 Spring WebFlux 模板支持 模板可由外部源编辑,因为这可能会产生安全隐患。 |
Spring WebFlux 应用程序的视图位于内部信任边界内 的应用程序。视图可以访问应用程序上下文中的 bean,并且 因此,我们不建议在满足以下条件的应用程序中使用 Spring WebFlux 模板支持 模板可由外部源编辑,因为这可能会产生安全隐患。 |
百里香叶
Thymeleaf 是一个现代的服务器端 Java 模板引擎,强调自然 HTML 可以通过双击在浏览器中预览的模板,这非常 有助于独立处理 UI 模板(例如,由设计人员),而无需 正在运行的服务器。Thymeleaf 提供了一组广泛的功能,并且正在积极开发 并维持。有关更完整的介绍,请参阅 Thymeleaf 项目主页。
Thymeleaf 与 Spring WebFlux 的集成由 Thymeleaf 项目管理。这
配置涉及一些 bean 声明,例如 、 和 。有关详细信息,请参阅 Thymeleaf+Spring 和 WebFlux 集成公告。SpringResourceTemplateResolver
SpringWebFluxTemplateEngine
ThymeleafReactiveViewResolver
自由标记
Apache FreeMarker 是一个模板引擎,用于生成任何 从 HTML 到电子邮件等的文本输出类型。Spring Framework 内置了 用于将 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")
}
}
您的模板需要存储在 指定的目录中 ,
如前面的示例所示。给定上述配置,如果您的控制器
返回视图名称 ,解析程序将查找模板。FreeMarkerConfigurer
welcome
classpath:/templates/freemarker/welcome.ftl
FreeMarker 配置
你可以通过设置适当的 bean 将 FreeMarker 'Settings' 和 'SharedVariables' 直接传递给 FreeMarker 对象(由 Spring 管理)。
属性。该属性需要
对象,并且该属性需要 .以下示例演示如何使用 :Configuration
FreeMarkerConfigurer
freemarkerSettings
java.util.Properties
freemarkerVariables
java.util.Map
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()))
}
}
请参阅 FreeMarker 文档,了解设置和变量的详细信息,因为它们适用于这些设置
对象。Configuration
表单处理
Spring 提供了一个标记库,用于 JSP,其中包括一个元素。此元素主要允许表单显示来自
表单支持对象,并显示
Web 或业务层。Spring 在 FreeMarker 中也支持相同的功能,
具有用于生成表单输入元素本身的附加便捷宏。<spring:bind/>
Validator
Bind 宏
文件中维护了一组标准的宏
FreeMarker,因此它们始终可用于适当配置的应用程序。spring-webflux.jar
Spring 模板库中定义的一些宏被认为是内部的
(私有),但宏定义中不存在此类范围,从而使所有宏都可见
调用代码和用户模板。以下各节仅重点介绍宏
您需要直接从模板中调用。如果要查看宏代码
直接调用该文件,并位于包中。spring.ftl
org.springframework.web.reactive.result.view.freemarker
有关绑定支持的更多详细信息,请参阅 Spring MVC 的简单绑定。
脚本视图
Spring Framework 有一个内置的集成,用于将 Spring WebFlux 与任何 可以在 JSR-223 Java 脚本引擎上运行的模板库。 下表显示了我们在不同脚本引擎上测试的模板库:
脚本库 | 脚本引擎 |
---|---|
集成任何其他脚本引擎的基本规则是它必须实现 and 接口。ScriptEngine Invocable |
要求
您需要在 Classpath 上具有脚本引擎,其详细信息因脚本引擎而异:
-
Nashorn JavaScript 引擎随 Java 8+ 的强烈建议使用可用的最新更新版本。
-
应该将 JRuby 添加为 Ruby 支持的依赖项。
-
应将 Jython 添加为 Python 支持的依赖项。
-
org.jetbrains.kotlin:kotlin-script-util
dependency 并添加包含一行的文件以支持 Kotlin 脚本。有关更多详细信息,请参阅此示例。META-INF/services/javax.script.ScriptEngineFactory
org.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 renderingContext
:RenderingContext
,用于访问应用程序上下文、区域设置、模板加载程序和 URL(自 5.0 起)
Mustache.render()
与此签名本机兼容,因此您可以直接调用它。
如果您的模板技术需要一些自定义,则可以提供一个脚本,该脚本 实现自定义 render 函数。例如,Handlerbars 需要在使用模板之前编译模板,并且需要一个 polyfill 来模拟一些 浏览器工具在服务器端脚本引擎中不可用。 以下示例显示如何设置自定义 render 函数:
-
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 或
React 在 Nashorn 上运行。在这种情况下,由于此错误,需要 Java SE 8 Update 60,但通常是
建议在任何情况下使用最新的 Java SE 补丁版本。sharedEngine false |
polyfill.js
仅定义 Handlebars 正常运行所需的对象,
如以下代码段所示:window
var window = {};
此基本实现在使用模板之前对其进行编译。A 生产
ready 实现还应存储和重用缓存的模板或预编译的模板。
这可以在脚本端完成,也可以完成您需要的任何自定义(管理
模板引擎配置)。
以下示例显示了如何编译模板:render.js
function render(template, model) {
var compiledTemplate = Handlebars.compile(template);
return compiledTemplate(model);
}
脚本库 | 脚本引擎 |
---|---|
集成任何其他脚本引擎的基本规则是它必须实现 and 接口。ScriptEngine Invocable |
使用非线程安全时,需要将属性设置为
具有非并发性模板库的脚本引擎,例如 Handlebars 或
React 在 Nashorn 上运行。在这种情况下,由于此错误,需要 Java SE 8 Update 60,但通常是
建议在任何情况下使用最新的 Java SE 补丁版本。sharedEngine false |
HTML 片段
HTMX 和 Hotwire Turbo 强调 HTML over-the-wire 方法,其中客户端以 HTML 而不是 JSON 格式接收服务器更新。 这允许 SPA(单页应用程序)的好处,而无需编写太多甚至 任何 JavaScript。如需良好的概述和了解更多信息,请访问他们各自的 网站。
在 Spring WebFlux 中,视图渲染通常涉及指定一个视图和一个模型。
但是,在 HTML-over-the-wire 中,一个常见的功能是发送多个 HTML 片段,这些片段
浏览器可用于更新页面的不同部分。为此,控制器方法
可以返回 。例如:Collection<Fragment>
-
Java
-
Kotlin
@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 来完成相同的操作:FragmentsRendering
-
Java
-
Kotlin
@GetMapping
FragmentsRendering handle() {
return FragmentsRendering.with("posts").fragment("comments").build();
}
@GetMapping
fun handle(): FragmentsRendering {
return FragmentsRendering.with("posts").fragment("comments").build()
}
每个 fragment 都可以有一个独立的模型,并且该模型从 请求的共享模型。
HTMX 和 Hotwire Turbo 支持通过 SSE(服务器发送的事件)流式传输更新。
控制器可以使用 、 或任何其他
反应式生产者,可通过 .
也可以在没有包装器的情况下直接返回。FragmentsRendering
Flux<Fragment>
Publisher
ReactiveAdapterRegistry
Flux<Fragment>
FragmentsRendering
JSON 和 XML
出于 Content Negotiation 目的,能够交替使用
使用 HTML 模板或其他格式(如 JSON 或 XML)渲染模型之间,
取决于客户端请求的内容类型。为了支持这样做,Spring WebFlux
提供 ,您可以使用它从 中插入任何可用的编解码器,例如 、 、
或。HttpMessageWriterView
spring-web
Jackson2JsonEncoder
Jackson2SmileEncoder
Jaxb2XmlEncoder
与其他视图技术不同,它不需要 a,而是配置为默认视图。您可以
配置一个或多个这样的默认视图,包装不同的实例
或 instances 的 S 。在运行时使用与请求的内容类型匹配的 URL。HttpMessageWriterView
ViewResolver
HttpMessageWriter
Encoder
在大多数情况下,一个模型包含多个属性。要确定要序列化的 Cookie,
您可以使用 model 属性的名称进行配置,以用于
渲染。如果模型仅包含一个属性,则使用该属性。HttpMessageWriterView