---
title: Spring MVC 之视图技术
date: 2023-02-17 11:21:25
order: 06
categories:
- Java
- 框架
- Spring
- SpringWeb
tags:
- Java
- 框架
- Spring
- Web
- View
permalink: /pages/264d3a22/
---
# Spring MVC 之视图技术
Spring MVC 中视图技术的使用是可插拔的。无论决定使用 Thymeleaf、Groovy 等模板引擎、JSP 还是其他技术,都可以通过配置来更改。
Spring MVC 的视图位于该应用程序的内部信任边界内。 视图可以访问应用程序上下文的所有 bean。 因此,不建议在模板可由外部源编辑的应用程序中使用 Spring MVC 的模板支持,因为这可能会产生安全隐患。
## Thymeleaf
[Thymeleaf](https://www.thymeleaf.org/) 是一个现代服务器端 Java 模板引擎,它强调自然的 HTML 模板,可以通过双击在浏览器中预览,而无需运行服务器,这对于 UI 模板的独立工作(例如,由设计师)非常有帮助。
Thymeleaf 与 Spring MVC 的集成由 Thymeleaf 项目管理。 配置涉及一些 bean 声明,例如 `ServletContextTemplateResolver`、`SpringTemplateEngine` 和 `ThymeleafViewResolver`。 有关详细信息,请参阅 [Thymeleaf+Spring](https://www.thymeleaf.org/documentation.html)。
## FreeMarker
[Apache FreeMarker](https://freemarker.apache.org/) 是一个模板引擎,用于生成从 HTML 到电子邮件等任何类型的文本内容。 Spring 框架内置了 Spring MVC 与 FreeMarker 模板结合使用的集成。
### 视图配置
以下示例显示了如何将 FreeMarker 配置为视图技术:
```java
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@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;
}
}
```
以下示例显示了如何在 XML 中配置相同的内容:
```xml
```
或者,您也可以声明 `FreeMarkerConfigurer` 以完全控制所有属性,如以下示例所示:
```xml
```
您的模板需要存储在前面示例中所示的 `FreeMarkerConfigurer` 指定的目录中。鉴于前面的配置,如果您的控制器返回视图名称 `welcome`,解析器将查找 `/WEB-INF/freemarker/welcome.ftl` 模板。
### FreeMarker 配置
可以通过在 `FreeMarkerConfigurer` 上设置适当的 bean 属性,将 FreeMarker 'Settings' 和 'SharedVariables' 直接传递给 FreeMarker `Configuration` 对象(由 Spring 管理)。 `freemarkerSettings` 属性需要一个 `java.util.Properties` 对象,`freemarkerVariables` 属性需要一个 `java.util.Map`。 以下示例显示了如何使用 `FreeMarkerConfigurer`:
```xml
```
有关应用于 `Configuration` 对象的设置和变量的详细信息,请参阅 FreeMarker 文档。
### 表单处理
Spring 提供了一个用于 JSP 的标记库,其中包含一个 `` 元素。 此元素主要让表单显示来自表单支持对象的值,并显示来自 Web 或业务层中的“验证器”的验证失败的结果。 Spring 还支持 FreeMarker 中的相同功能,以及用于生成表单输入元素的额外便利宏。
#### 绑定宏
在 FreeMarker 的 `spring-webmvc.jar` 文件中维护了一组标准宏,因此它们始终可用于适当配置的应用程序。
Spring 模板库中定义的一些宏被认为是内部的(私有的),但宏定义中不存在这样的范围,这使得所有宏对调用代码和用户模板都是可见的。以下部分仅关注您需要从模板中直接调用的宏。如果您想直接查看宏代码,该文件名为 `spring.ftl` ,位于 `org.springframework.web.servlet.view.freemarker` 包中。
#### 简单绑定
在基于充当 Spring MVC 控制器表单视图的 FreeMarker 模板的 HTML 表单中,您可以使用类似于下一个示例的代码来绑定到字段值,并以类似于 JSP 等价物的方式为每个输入字段显示错误消息。以下示例显示了一个 personForm 视图:
```xml
<#import "/spring.ftl" as spring/>
...
...
```
`<@spring.bind>` 需要一个 'path' 参数,它由命令对象的名称(它是 'command',除非您在控制器配置中更改它)组成,在您希望绑定的命令对象后跟一个句点和字段名称。 您还可以使用嵌套字段,例如 `command.address.street`。 `bind` 宏采用 `web.xml` 中的 `ServletContext` 参数 `defaultHtmlEscape` 指定的默认 HTML 转义行为。
称为 `<@spring.bindEscaped>` 的宏的另一种形式采用第二个参数,该参数明确指定是否应在状态错误消息或值中使用 HTML 转义。 您可以根据需要将其设置为 `true` 或 `false` 。 附加的表单处理宏简化了 HTML 转义的使用,您应该尽可能使用这些宏。
#### 输入宏
FreeMarker 的附加便利宏简化了绑定和表单生成(包括验证错误显示)。 永远不需要使用这些宏来生成表单输入字段,您可以将它们与简单的 HTML 混合搭配,或者直接调用我们之前强调的 Spring 绑定宏。
下表中的可用宏显示了 FreeMarker 模板 (FTL) 定义和每个采用的参数列表:
| macro | FTL definition |
| :------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------- |
| `message` (output a string from a resource bundle based on the code parameter) | <@spring.message code/> |
| `messageText` (output a string from a resource bundle based on the code parameter, falling back to the value of the default parameter) | <@spring.messageText code, text/> |
| `url` (prefix a relative URL with the application’s context root) | <@spring.url relativeUrl/> |
| `formInput` (standard input field for gathering user input) | <@spring.formInput path, attributes, fieldType/> |
| `formHiddenInput` (hidden input field for submitting non-user input) | <@spring.formHiddenInput path, attributes/> |
| `formPasswordInput` (standard input field for gathering passwords. Note that no value is ever populated in fields of this type.) | <@spring.formPasswordInput path, attributes/> |
| `formTextarea` (large text field for gathering long, freeform text input) | <@spring.formTextarea path, attributes/> |
| `formSingleSelect` (drop down box of options that let a single required value be selected) | <@spring.formSingleSelect path, options, attributes/> |
| `formMultiSelect` (a list box of options that let the user select 0 or more values) | <@spring.formMultiSelect path, options, attributes/> |
| `formRadioButtons` (a set of radio buttons that let a single selection be made from the available choices) | <@spring.formRadioButtons path, options separator, attributes/> |
| `formCheckboxes` (a set of checkboxes that let 0 or more values be selected) | <@spring.formCheckboxes path, options, separator, attributes/> |
| `formCheckbox` (a single checkbox) | <@spring.formCheckbox path, attributes/> |
| `showErrors` (simplify display of validation errors for the bound field) | <@spring.showErrors separator, classOrStyle/> |
上述任何宏的参数具有一致的含义:
- `path`: 要绑定到的字段的名称(例如,“command.name”)
- `options`: 可在输入字段中选择的所有可用值的 `Map`。映射的键表示从表单回传并绑定到命令对象的值。针对键存储的 map 对象是在表单上显示给用户的标签,可能与表单回传的相应值不同。通常,这样的地图由控制器提供作为参考数据。您可以使用任何 `Map` 实现,具体取决于所需的行为。对于严格排序的映射,您可以使用带有合适的“比较器”的 `SortedMap`(例如 `TreeMap`),对于应按插入顺序返回值的任意映射,使用“LinkedHashMap”或“LinkedMap” `公共收藏`。
- `separator`: 在多个选项可用作离散元素(单选按钮或复选框)的情况下,用于分隔列表中每个选项的字符序列(例如 ` `)。
- `attributes`: 要包含在 HTML 标记本身中的任意标记或文本的附加字符串。该字符串按字面意思由宏回显。例如,在 `textarea` 字段中,您可以提供属性(例如“rows="5" cols="60"'),或者您可以传递样式信息,例如 'style="border:1px solid silver"'。
- `classOrStyle`: 对于 `showErrors` 宏,包装每个错误的 `span` 元素使用的 CSS 类的名称。如果未提供任何信息(或值为空),错误将包含在 `` 标签中。
以下部分概述了宏的示例。
输入字段
`formInput` 宏采用 `path` 参数 (`command.name`) 和一个额外的 `attributes` 参数(在接下来的示例中为空)。该宏与所有其他表单生成宏一起对路径参数执行隐式 Spring 绑定。绑定在新绑定发生之前一直有效,因此 `showErrors` 宏不需要再次传递路径参数——它对上次创建绑定的字段进行操作。
`showErrors` 宏接受一个分隔符参数(用于分隔给定字段上的多个错误的字符),还接受第二个参数——这次是类名或样式属性。请注意,FreeMarker 可以为 attributes 参数指定默认值。以下示例显示了如何使用 `formInput` 和 `showErrors` 宏:
```xml
<@spring.formInput "command.name"/>
<@spring.showErrors " "/>
```
下一个示例显示表单片段的输出,生成名称字段并在表单提交后显示验证错误,该字段中没有任何值。验证通过 Spring 的验证框架进行。
生成的 HTML 类似于以下示例:
```html
Name:
required