概要

<#include path><#include path options>

这里:

  • path: 要包含文件的路径;一个算作是字符串的表达式。(用其他话说, 它不用是一个固定的字符串,它也可以是像 profile.baseDir + "/menu.ftl"这样的东西。)
  • options: 一个或多个这样的选项: encoding=encoding, parse=parse
    • encoding: 算作是字符串的表达式
    • parse: 算作是布尔值的表达式(为了向下兼容,也接受一部分字符串值)
    • ignore_missing: 算作是布尔值的表达式

描述

你可以使用它在你的模板中插入另外一个 FreeMarker 模板文件 (由 path 参数指定)。 被包含模板的输出格式是在 include 标签出现的位置插入的。 被包含的文件和包含它的模板共享变量,就像是被复制粘贴进去的一样。 include 指令不能由被包含文件的内容所替代, 它只是当 FreeMarker 每次在模板处理期间到达 include 指令时处理被包含的文件。所以对于如果 includelist 循环之中的例子, 你可以为每个循环周期内指定不同的文件名。

Note:

这个指令不能和JSP(Servlet)的include搞混, 因为它不涉及到Servlet容器中,只是处理应外一个FreeMarker模板, 不能"离开"FreeMarker。关于如何处理"JSP include",请阅读...

path 参数可以是如 "foo.ftl""../foo.ftl" 一样的相对路径,或者是如 "/foo.ftl" 这样的绝对路径。 相对路径是相对于使用 import 指令的模板文件夹。 绝对路径是相对于程序员在配置 FreeMarker 时定义的基路径 (通常指代"模板的根路径")。

Note:

这和 FreeMarker 2.1 版本之前的处理方式不同, 之前的路径通常是绝对路径。为了保留原来的行为, 要在 Configuration 对象中开启经典的兼容模式。

通常使用 /(斜杠)来分隔路径成分, 而不是 \(反斜杠)。如果你从你本地的文件系统加载模板, 而它使用反斜杠(像Windows操作系统),也要使用 /

比如:

假设 /common/copyright.ftl 包含:

Copyright 2001-2002 ${me}<br>
All rights reserved.

那么:

<#assign me = "Juila Smith">
<h1>Some test</h1>
<p>Yeah.
<hr>
<#include "/common/copyright.ftl">

将会输出:

<h1>Some test</h1>
<p>Yeah.
<hr>
Copyright 2001-2002 Juila Smith
All rights reserved.

支持的 options 选项有:

  • parse:如果它为 true, 那么被包含的文件将会当作FTL来解析,否则整个文件将被视为简单文本 (也就是说不会在其中查找 FreeMarker 的结构)。如果你忽略了这个选项, 那么它默认是 true

  • encoding:被包含文件从包含它的文件继承的编码方式 (实际就是字符集),除非你用这个选项来指定编码方式。 合法的名字有:ISO-8859-2,UTF-8,Shift_JIS,Big5,EUC-KR,GB2312。 编码名称要和java.io.InputStreamReader 中支持的那些一致(对于Java API 1.3版本:MIME 希望的字符集是从IANA字符集注册处得到的)

  • ignore_missing:当为 true,模板引用为空时压制错误,而 <#include ...> 不会输出任何东西。当为 false 时,如果模板不存在, 那么模板处理就会发生错误并停止。如果忽略这个选项,那么它的默认值是 false

比如:

<#include "/common/navbar.html" parse=false encoding="Shift_JIS">

请注意, 对于所有模板可能会用 Configuration 的"自动包含"设置自动处理通用的包含物。

使用获得机制

有一个特殊的路径组成,是用一个星号(*)来代表的。 它被解释为"当前目录或其他任意它的父目录"。因此, 如果模板在 /foo/bar/template.ftl 位置上,有下面这行:

<#include "*/footer.ftl">

那么引擎就会在下面的位置上寻找模板,并按这个顺序:

  • /foo/bar/footer.ftl
  • /foo/footer.ftl
  • /footer.ftl

该机制被称为 acquisition 并允许设计者在父目录中放置通用的被包含的文件, 而且当需要时在每个子路径基础上重新定义它们。 我们说包含它们的模板获得了从包含它的第一个父目录中的模板。请注意, 你不但可以在星号的右面指定一个模板的名字,也可以指定一个子路径。 也就是说,如果前面的模板由下面这个所替代:

<#include "*/commons/footer.ftl">

那么引擎将会从下面的路径开始寻找模板,并按这个顺序:

  • /foo/bar/commons/footer.ftl
  • /foo/commons/footer.ftl
  • /commons/footer.ftl

最终,星号不再是路径的第一个元素:

<#include "commons/*/footer.ftl">

会让引擎将会从下面的路径开始寻找模板,并按这个顺序:

  • /foo/bar/commons/footer.ftl
  • /foo/bar/footer.ftl
  • /foo/footer.ftl
  • /footer.ftl

然而,在路径中最多只能有一个星号。 指定多余一个星号会导致模板不能被发现。

本地化查找

本地化是语言和可选的国家或方言标识符 (加上可能的更多变体标识符,比如 "MAC")。 无论何时模板被请求,期望的本地化都会被指定(明确或含蓄), FreeMarker 会试图找到变化的模板来匹配本地化环境。当模板包含或引入其它模板时, 在内部也会被请求一个本地化环境,也就是 locale 配置的本地化, 通常它是顶级模板的本地化设置。

假设模板使用本地化 en_US 来加载, 就是美国英语。当包含其它模板时:

<#include "footer.ftl">

引擎实际上就会寻找一些模板,并按照这个顺序:

  • footer_en_US.ftl,
  • footer_en.ftl
  • footer.ftl

它会使用第一个存在的。

请注意,如果 FreeMarker 查找的本地化变化是由程序员配置的, 那么这里我们只能描述默认的行为。 可以使用 localized_lookup 设置来禁用本地化查找 (Configuration.setLocalizedLookup(boolean))。 而且,可以使用 template_lookup_strategy 设置来自行定义推导出的模板名称序列 (Configuration.setTemplateLookupStrategy(TemplateLookupStrategy))。

当你同时使用获得机制(也就是路径中的 * 步骤) 和本地化查找时,在父目录中有指定本地化的模板优先于在子目录中有很少本地化的模板。 假设你使用下面的代码来包含 /foo/bar/template.ftl

<#include "*/footer.ftl">

引擎将会查找这些模板,并按照这个顺序:

  • /foo/bar/footer_en_US.ftl
  • /foo/footer_en_US.ftl
  • /footer_en_US.ftl
  • /foo/bar/footer_en.ftl
  • /foo/footer_en.ftl
  • /footer_en.ftl
  • /foo/bar/footer.ftl
  • /foo/footer.ftl
  • /footer.ftl