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 -->