# 1.9 View Technologies

Spring WebFlux中视图技术的使用是可插入的，无论您决定使用Thymeleaf，Groovy标记模板，JSP还是其他技术，主要取决于配置更改。 本章介绍与Spring WebFlux集成的视图技术。 我们假设您已经熟悉View Resolution。

## 1.9.1 Thymeleaf

Thymeleaf是一种现代的服务器端Java模板引擎，它强调可以通过双击在浏览器中预览的自然HTML模板，这对于独立处理UI模板（例如，由设计人员）而无需使用非常有用。 正在运行的服务器。 如果要替换JSP，Thymeleaf提供了最广泛的功能集之一，以使这种过渡更加容易。 Thymeleaf是积极开发和维护的。 有关更完整的介绍，请参见Thymeleaf项目主页。

Thymeleaf与Spring MVC的集成由Thymeleaf项目管理。 该配置涉及一些Bean声明，例如ServletContextTemplateResolver，SpringTemplateEngine和ThymeleafViewResolver。 有关更多详细信息，请参见Thymeleaf + Spring。

## 1.9.2 FreeMarker

Apache FreeMarker是一个模板引擎，用于生成从HTML到电子邮件等的任何类型的文本输出。 Spring框架具有内置的集成，可以将Spring MVC与FreeMarker模板一起使用。

**View配置**

以下示例显示如何将FreeMarker配置为一种视图技术：

```java
@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("/WEB-INF/freemarker");
        return configurer;
    }
}
```

您的模板需要存储在上例所示的FreeMarkerConfigurer指定的目录中。 给定上述配置，如果您的控制器返回欢迎的视图名称，则解析器将查找/WEB-INF/freemarker/welcome.ftl模板。

**FreeMarker Configuration**

您可以通过在FreeMarkerConfigurer bean上设置适当的bean属性，将FreeMarker的“设置”和“ SharedVariables”直接传递给FreeMarker配置对象（由Spring管理）。 freemarkerSettings属性需要一个java.util.Properties对象，而freemarkerVariables属性需要一个java.util.Map。 以下示例显示了如何使用FreeMarkerConfigurer：

```java
@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对象的详细信息，请参见FreeMarker文档。

## 1.9.3 Script Views

Spring框架具有内置的集成，可以将Spring MVC与可以在JSR-223 Java脚本引擎之上运行的任何模板库一起使用。 我们已经在不同的脚本引擎上测试了以下模板库：

| Scripting Library        | Scripting Engine |
| ------------------------ | ---------------- |
| Handlebars               | Nashorn          |
| Mustache                 | Nashorn          |
| React                    | Nashorn          |
| EJS                      | Nashorn          |
| ERB                      | JRuby            |
| String templates         | Jython           |
| Kotlin Script templating | Kotlin           |

> 集成任何其他脚本引擎的基本规则是，它必须实现ScriptEngine和Invocable接口。

**Requirements**

您需要在类路径上具有脚本引擎，其细节因脚本引擎而异：

* Java 8+随附了Nashorn JavaScript引擎。 强烈建议使用可用的最新更新版本。
* 应该将JRuby添加为对Ruby支持的依赖。
* 应该将Jython添加为对Python支持的依赖项。
* 应该添加org.jetbrains.kotlin：kotlin-script-util依赖项和包含org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory行的META-INF / services / javax.script.ScriptEngineFactory文件。 有关更多详细信息，请参见此示例。

您需要具有脚本模板库。 针对Javascript的一种方法是通过WebJars。

**Script Templates**

您可以声明一个ScriptTemplateConfigurer bean来指定要使用的脚本引擎，要加载的脚本文件，调用呈现模板的函数等等。 以下示例使用Mustache模板和Nashorn JavaScript引擎：

```java
@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;
    }
}
```

使用以下参数调用render函数：

* String template：模板内容
* Map model：视图模型
* RenderingContext renderingContext：RenderingContext，用于访问应用程序上下文，语言环境，模板加载器和URL（自5.0起）

Mustache.render（）与该签名本地兼容，因此您可以直接调用它。

如果您的模板技术需要一些自定义，则可以提供一个实现自定义渲染功能的脚本。 例如，Handlerbars需要在使用模板之前先对其进行编译，并且需要使用polyfill来模拟某些服务器端脚本引擎中不可用的浏览器功能。

以下示例显示了如何执行此操作：

```java
@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;
    }
}
```

当您将非线程安全脚本引擎与不是为并发设计的模板库一起使用时，例如，在Nashorn上运行的Handlebars或React，必须将sharedEngine属性设置为false。 在这种情况下，由于此错误，需要Java 8u60或更高版本。

polyfill.js仅定义Handlebars正常运行所需的window对象，如下所示：

```javascript
var window = {};
```

这个基本的render.js实现在使用模板之前先对其进行编译。 生产就绪的实现还应该存储任何重用的缓存模板或预编译的模板。 您可以在脚本方面进行操作（并处理所需的任何自定义，例如管理模板引擎配置）。 以下示例显示了如何执行此操作：

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

## 1.9.4 JSON and XML

出于内容协商的目的，根据客户端请求的内容类型，能够在使用HTML模板呈现模型或以其他格式（例如JSON或XML）呈现模型之间进行切换非常有用。为了支持此操作，Spring WebFlux提供了HttpMessageWriterView，您可以使用它插入spring-web中的任何可用编解码器，例如Jackson2JsonEncoder，Jackson2SmileEncoder或Jaxb2XmlEncoder。

与其他视图技术不同，HttpMessageWriterView不需要ViewResolver，而是配置为默认视图。您可以配置一个或多个此类默认视图，并包装不同的HttpMessageWriter实例或Encoder实例。在运行时使用与请求的内容类型匹配的内容。

在大多数情况下，模型包含多个属性。要确定要序列化的对象，可以使用模型属性的名称配置HttpMessageWriterView进行渲染。如果模型仅包含一个属性，则使用该属性。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.flydean.com/spring-framework-documentation5/webreactive/1.spring-webflux/1.9view-technologies.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
