|
对于最新的稳定版本,请使用 Spring Framework 7.0.6! |
视图技术
Spring WebFlux 中视图技术的使用是可插拔的。无论您决定使用 Thymeleaf、FreeMarker 还是其他视图技术,主要是一个配置更改的问题。本章将介绍与 Spring WebFlux 集成的视图技术。我们假设您已经熟悉了视图解析。
百里叶
Thymeleaf 是一个现代的服务器端 Java 模板引擎,它强调自然的 HTML 模板,可以通过双击在浏览器中预览,这对于独立进行 UI 模板工作(例如,由设计师)非常有帮助,而无需运行服务器。Thymeleaf 提供了广泛的功能,并且正在积极开发和维护中。有关更完整的介绍,请参阅 Thymeleaf 项目主页。
Thymeleaf与Spring WebFlux的集成由Thymeleaf项目管理。配置涉及一些bean声明,例如
SpringResourceTemplateResolver, SpringWebFluxTemplateEngine, 和
ThymeleafReactiveViewResolver. 有关更多详细信息,请参阅
Thymeleaf+Spring 和WebFlux集成的
公告。
自由标记
Apache FreeMarker 是一个模板引擎,用于生成从 HTML 到电子邮件等各种类型的文本输出。Spring 框架内置了使用 Spring WebFlux 和 FreeMarker 模板的集成。
查看配置
以下示例展示了如何将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 配置
您可以直接将FreeMarker的“设置”和“共享变量”传递给由Spring管理的FreeMarker
Configuration 对象,方法是设置FreeMarkerConfigurer bean的相应bean属性。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 使用,其中包含一个 <spring:bind/> 元素。此元素主要用于让表单显示来自表单支持对象的值,并显示来自 web 或业务层中的 Validator 的验证失败结果。Spring 还支持在 FreeMarker 中使用相同的功能,并提供了额外的便利宏来生成表单输入元素。
绑定宏
一组标准的宏在spring-webflux.jar文件中维护,用于FreeMarker,因此它们始终可用于配置适当的应用程序。
Spring模板库中定义的一些宏被认为是内部的(私有的),但宏定义中没有这样的作用域,使得所有宏对调用代码和用户模板都是可见的。以下部分仅集中于你需要直接在模板中调用的宏。如果你想直接查看宏代码,文件名为spring.ftl,位于org.springframework.web.reactive.result.view.freemarker包中。
有关绑定支持的详细信息,请参阅简单绑定以了解Spring MVC。
脚本视图
Spring框架内置了使用Spring WebFlux与任何可以在JSR-223 Java脚本引擎上运行的模板库集成的功能。 下表列出了我们在不同脚本引擎上测试过的模板库:
| 脚本库 | 脚本引擎 |
|---|---|
集成任何其他脚本引擎的基本规则是,它必须实现ScriptEngine和Invocable接口。 |
要求
你需要将脚本引擎添加到你的类路径中,具体细节因脚本引擎而异:
-
The Nashorn JavaScript引擎是随Java 8+提供的。建议使用最新的更新版本。
-
JRuby 应该被添加为依赖以支持 Ruby。
-
Jython 应该被添加为依赖以支持Python。
-
org.jetbrains.kotlin:kotlin-script-util个依赖项和一个META-INF/services/javax.script.ScriptEngineFactory文件,其中包含org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory行应被添加以支持Kotlin脚本。请参见 这个示例 以获取更多详细信息。
你需要拥有脚本模板库。对于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"
}
}
The 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是在使用非线程安全的脚本引擎和未设计为支持并发的模板库(如Handlebars或在Nashorn上运行的React)时所必需的。在这种情况下,需要Java SE 8更新60,因为这个bug,但通常建议使用最近的Java SE补丁版本。 |
polyfill.js 定义了 Handlebars 正常运行所需的 window 对象,
如下所示的代码片段:
var window = {};
这个基本的render.js实现会在使用模板之前对其进行编译。一个生产环境的实现还应该存储和重用缓存的模板或预编译的模板。这可以在脚本侧完成,以及任何你需要的自定义(例如管理模板引擎配置)。
以下示例展示了如何编译模板:
function render(template, model) {
var compiledTemplate = Handlebars.compile(template);
return compiledTemplate(model);
}
JSON 和 XML
对于内容协商的目的,能够根据客户端请求的内容类型在使用HTML模板渲染模型和以其他格式(如JSON或XML)之间切换是有用的。为此,Spring WebFlux提供了HttpMessageWriterView,你可以使用它来插入任何可用的编解码器从spring-web,例如Jackson2JsonEncoder、Jackson2SmileEncoder或Jaxb2XmlEncoder。
与其它视图技术不同,HttpMessageWriterView 不需要 ViewResolver,而是作为默认视图进行配置。您可以配置一个或多个这样的默认视图,封装不同的 HttpMessageWriter 实例或 Encoder 实例。运行时将使用匹配请求内容类型的那一个。
在大多数情况下,模型包含多个属性。要确定要序列化的属性,你可以通过配置HttpMessageWriterView来指定要用于渲染的模型属性名称。如果模型只包含一个属性,则使用该属性。