19.4 FreeMarker
FreeMarker是一种模板语言,可以用作Spring MVC应用程序中的视图技术. 更多关于模板语言的信息,请点击站点 FreeMarker .
19.4.1 依赖
您的Web应用程序需要包含freemarker-2.x.jar才能使用FreeMarker。 通常这包含在WEB-INF / lib文件夹中,其中jar保证由Java EE服务器找到并添加到应用程序的类路径中。 当然,假设你已经有spring-webmvc.jar在你的’WEB-INF / lib’目录了!
19.4.2 上下文配置
通过将相关的configurer bean定义添加到您的’* -servlet.xml’来初始化一个合适的配置,如下所示:
<!-- freemarker config -->
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/freemarker/"/>
</bean>
<!--
View resolvers can also be configured with ResourceBundles or XML files. If you need
different view resolving based on Locale, you have to use the resource bundle resolver.
-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".ftl"/>
</bean>
对于非web项目,在你定义的上下文中增加
FreeMarkerConfigurationFactoryBean
19.4.3 创建模板
您的模板需要存储在上面显示的FreeMarkerConfigurer指定的目录中。 如果您使用突出显示的视图解析器,则逻辑视图名称与模板文件名称以类似于JSP的InternalResourceViewResolver的方式相关。 因此,如果您的控制器返回一个包含视图名称为“welcome”的ModelAndView对象,则解析器将查找/WEB-INF/freemarker/welcome.ftl模板。
19.4.4 高级FreeMarker配置
FreeMarker的’Settings’和’SharedVariables’可以直接传递给由Spring管理的FreeMarker Configuration对象,方法是在FreeMarkerConfigurer bean上设置相应的bean属性。 freemarkerSettings属性需要一个java.util.Properties对象,而freemarkerVariables属性需要一个java.util.Map。
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/freemarker/"/>
<property name="freemarkerVariables">
<map>
<entry key="xml_escape" value-ref="fmXmlEscape"/>
</map>
</property>
</bean>
<bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape"/>
有关设置和变量的详细信息,请参阅FreeMarker文档,因为它们适用于Configuration对象。
19.4.5绑定支持和表单处理
Spring提供了一个用于JSP的标签库,其中包含(其中包含)<spring:bind />标签。 此标记主要允许表单从表单支持对象显示值,并显示来自网络或业务层的验证程序的失败验证结果。 Spring还支持FreeMarker中的相同功能,还有其他方便的宏用于生成表单输入元素。
绑定宏
在双方语言的spring-webmvc.jar文件中都保留了一组标准的宏,因此它们始终可供适当配置的应用程序使用。
在Spring库中定义的一些宏被认为是内部的(私有的),但在宏定义中不存在这样的范围,使所有的宏都可以被调用代码和用户模板。 以下部分仅出现在您在模板中直接调用的宏。 如果您希望直接查看宏代码,则该文件在包org.springframework.web.servlet.view.freemarker中称为spring.ftl。
简单绑定
在作为Spring MVC控制器的窗体视图的HTML表单(vm / ftl模板)中,您可以使用与以下类似的代码绑定到字段值,并以与JSP等效的类似方式显示每个输入字段的错误消息。 下面列出了以前配置的personForm视图的示例代码:
<!-- freemarker macros have to be imported into a namespace. We strongly
recommend sticking to 'spring' -->
<#import "/spring.ftl" as spring/>
<html>
...
<form action="" method="POST">
Name:
<@spring.bind "myModelObject.name"/>
<input type="text"
name="${spring.status.expression}"
value="${spring.status.value?html}"/><br>
<#list spring.status.errorMessages as error> <b>${error}</b> <br> </#list>
<br>
...
<input type="submit" value="submit"/>
</form>
...
</html>
<@ spring.bind>需要一个“path”参数,它由命令对象的名称组成(除非您在FormController属性中更改它,否则将是“command”),后跟一个句点和该命令上的字段名称 您要绑定到的对象。 也可以使用嵌套字段,如“command.address.street”。 bind macro 假定web.xml中ServletContext参数defaultHtmlEscape指定的默认HTML转义行为。
称为<@ spring.bindEscaped>的宏的可选格式需要第二个参数,并显式指定是否在状态错误消息或值中使用HTML转义。 根据需要设置为true或false。 附加的表单处理宏简化了HTML转义的使用,并且尽可能使用这些宏。 他们将在下一节中进行说明。
表单输入生成宏
两种语言的其他便利宏简化了绑定和表单生成(包括验证错误显示)。 从来没有必要使用这些宏来生成表单输入字段,并且可以混合使用简单的HTML或直接调用前面突出显示的弹簧绑定宏。
可用宏的下表显示了VTL和FTL定义以及每个参数列表。
宏 | FTL 定义 | 消息(根据代码参数从资源束输出字符串) |
---|---|---|
<@spring.message code/> | messageText(根据代码参数从资源束输出一个字符串,退回到默认参数的值) | <@spring.messageText code, text/> |
url(使用应用程序的上下文根前缀相对URL) | <@spring.url relativeUrl/> | formInput(用于收集用户输入的标准输入字段) |
<@spring.formInput path, attributes, fieldType/> | formHiddenInput* (用于提交非用户输入的隐藏输入字段) | <@spring.formHiddenInput path, attributes/> |
formPasswordInput* (用于收集密码的标准输入字段。 请注意,不会在此类型的字段中填充任何值) | <@spring.formPasswordInput path, attributes/> | formTextarea(大文本字段用于收集长,自由格式的文本输入) |
<@spring.formTextarea path, attributes/> | formSingleSelect(d下拉框选项允许选择单个所需的值) | <@spring.formSingleSelect path, options, attributes/> |
formMultiSelect(允许用户选择0个或更多值的选项列表框) | <@spring.formMultiSelect path, options, attributes/> | formRadioButtons(一组单选按钮允许从可用选项中进行单次选择) |
<@spring.formRadioButtons path, options separator, attributes/> | formCheckboxes(一组允许选择0个或更多值的复选框) | <@spring.formCheckboxes path, options, separator, attributes/> |
formCheckbox(a single checkbox) | <@spring.formCheckbox path, attributes/> | showErrors(简化显示绑定字段的验证错误) |
- 在FTL(FreeMarker)中,这两个宏并不是实际需要的,因为您可以使用正常的formInput宏,指定’hidden’或’`password’作为`fieldType参数的值。.
任何上述宏的参数具有一致的含义:
- path: 要绑定的字段的名称(如:“command.name”)
- 选项: 可以在输入字段中选择的所有可用值的映射。地图的键代表将从窗体返回并绑定到命令对象的值。按键显示的映射对象是表单上显示给用户的标签,可能与表单发回的对应值不同。通常这样的地图由控制器作为参考数据提供。可以根据需要的行为使用任何Map实现。对于严格排序的映射,可以使用诸如具有适当比较器的TreeMap的SortedMap,并且可以使用应该以插入顺序返回值的任意地图,使用commons-collections中的LinkedHashMap或LinkedMap
- 分隔符:多个选项可用作谨慎元素(单选按钮或复选框),用于分隔列表中每个选项的字符序列(即“<br>”). 属性:要包含在HTML标签本身中的任意标签或文本的附加字符串。该字符串由字符串回显。例如,在textarea字段中,您可以提供“rows =”5“cols =”60“’的属性,或者您可以传递样式信息,如”style =“border:1px solid silver”
- classOrStyle:对于showErrors宏,包含每个错误的span标签将使用的CSS类的名称。如果没有提供信息(或值为空),那么错误将被包裹在<b> </ b>标签中。
宏中的一些例子在FTL和VTL中的一些中概述。在两种语言之间存在使用差异的情况下,它们将在说明中进行说明。
输入的值
formInput宏在上面的示例中使用path参数(command.name)和一个空的附加属性参数。 宏与所有其他表单生成宏一起在路径参数上执行隐式弹簧绑定。 绑定保持有效,直到发生新的绑定,因此showErrors宏不需要再次传递路径参数 – 它只是在上次创建绑定的字段时操作。
showErrors宏采用一个分隔符参数(用于在给定字段上分隔多个错误的字符),并且还接受第二个参数,此时为类名或样式属性。 请注意,FreeMarker能够为attributes参数指定默认值。
<@spring.formInput "command.name"/>
<@spring.showErrors "<br>"/>
输出显示在生成名称字段的表单片段中,并在表单提交后在该字段中没有值显示验证错误。 验证通过Spring的验证框架进行。
生成的HTML如下所示:
Name:
<input type="text" name="name" value="">
<br>
<b>required</b>
<br>
<br>
formTextarea宏的工作方式与formInput宏相同,并接受相同的参数列表。 通常,第二个参数(属性)将用于传递文本区域的样式信息或行和列属性。
选择字段
四个选择字段宏可用于在HTML表单中生成常见的UI值选择输入。
- formSingleSelect
- formMultiSelect
- formRadioButtons
- formCheckboxes四个宏中的每一个接受一个包含表单字段的值的选项映射,以及与该值对应的标签。 该值和标签可以相同。FTL中的单选按钮示例如下。 表单后备对象为此字段指定了“伦敦”的默认值,因此不需要进行验证。 当表单呈现时,可以在模型中以“cityMap”的名称提供作为参考数据的整个城市列表。
...
Town:
<@spring.formRadioButtons "command.address.town", cityMap, ""/><br><br>
这将使用一个单选按钮,一个为cityMap中的每个值使用分隔符“”。 不提供其他属性(缺少宏的最后一个参数)。 cityMap对地图中的每个键值对使用相同的String。 地图的键是表单实际提交的POST请求参数,地图值是用户看到的标签。 在上面的例子中,给出了三个众所周知城市的列表和表单后备对象中的默认值,HTML将是
Town:
<input type="radio" name="address.town" value="London">London</input>
<input type="radio" name="address.town" value="Paris" checked="checked">Paris</input>
<input type="radio" name="address.town" value="New York">New York</input>
如果您的应用程序期望通过内部代码处理城市,则将使用如下面的示例的合适键创建代码映射。
protected Map<String, String> referenceData(HttpServletRequest request) throws Exception {
Map<String, String> cityMap = new LinkedHashMap<>();
cityMap.put("LDN", "London");
cityMap.put("PRS", "Paris");
cityMap.put("NYC", "New York");
Map<String, String> model = new HashMap<>();
model.put("cityMap", cityMap);
return model;
}
代码根据单选框的相关代码产生新的输出,但用户仍然会看到更友好的城市名称。
Town:
<input type="radio" name="address.town" value="LDN">London</input>
<input type="radio" name="address.town" value="PRS" checked="checked">Paris</input>
<input type="radio" name="address.town" value="NYC">New York</input>
HTML转义和符合XHTML标准
上述格式宏的默认使用将导致符合HTML 4.01的HTML标记,并且使用Spring绑定支持使用的web.xml中定义的HTML转义的默认值。 为了使标签符合XHTML或覆盖默认的HTML转义值,您可以在模板中指定两个变量(或者在模型中指定模板中可以看到的变量)。 在模板中指定它们的优点是,它们可以在模板处理中稍后更改为不同的值,以便为表单中的不同字段提供不同的行为。
要为您的标记切换到XHTML符合性,请为名为xhtmlCompliant的模型/上下文变量指定值“true”
<#-- for FreeMarker -->
<#assign xhtmlCompliant = true in spring>
处理此指令后,Spring宏生成的任何标签现在都符合XHTML标准。
以类似的方式,可以为每个字段指定HTML转义:
<#-- until this point, default HTML escaping is used -->
<#assign htmlEscape = true in spring>
<#-- next field will use HTML escaping -->
<@spring.formInput "command.name"/>
<#assign htmlEscape = false in spring>
<#-- all future fields will be bound with HTML escaping off -->