include 指令

本章节将介绍 FreeMaker 中的 <#include> 指令。主要内容如下:

<#include> 基础知识

您可以使用 include 指令在你的模板中插入另外一个 FreeMarker 模板文件,将在 include 指令出现的位置插入的被包含模版的内容。 被包含的模版文件和 include 指令所在的模板共享变量,就像是被复制粘贴进去的一样。语法如下:

<#include path>
<!-- 或 -->
<#include path options>

参数说明:

  • path: 要包含模版文件的路径,可以是一个字符串表达式。例如:profile.baseDir + "/menu.ftl"

  • options: 可选的,一个或多个选项: encoding=encoding, parse=parse

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

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

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

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

include 指令不能由被包含文件的内容所替代, 它只是当 FreeMarker 每次在模板处理期间到达 include 指令时处理被包含的文件。所以对于如果 include 在 list 循环之中的例子, 你可以为每个循环周期内指定不同的文件名。实例:

<html>
<head>
    <title>include 指令</title>
</head>
<body>

<#if message_type="email">
    <#include "sub/email.ftl">
<#elseif message_type="sms">
    <#include "sub/sms.ftl">
<#else>
    <#include "sub/default.ftl">
</#if>

</body>
</html>

上面实例中,将根据 message_type 变量来 include 不同的模版。如果 message_type 等于 “sms”,输出内容如下:

<html>
<head>
    <title>include 指令</title>
</head>
<body>
<div>
    <h2>一条短信</h2>
    <p>感谢您对《FreeMaker 零基础教程》的支持,^_^</p>
</div>
</body>
</html>

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

当然,我们还可以使用 encoding 来指定模版的编码,被包含模版默认继承包含它的模版的编码。例如:

<html>
<head>
    <title>include 指令</title>
</head>
<body>

<#if message_type="email">
    <#include "sub/email.ftl" encoding="GB2312">
<#elseif message_type="sms">
    <#include "sub/sms.ftl" encoding="GB2312">
<#else>
    <#include "sub/default.ftl" encoding="GB2312">
</#if>

</body>
</html>

<#include> 带 * 的 path

FreeMaker 的 include 指令 path 属性可以使用 *,星号(*)被解释为 "当前目录或其他任意它的父目录"。因此, 如果模板在 /foo/bar/template.ftl 位置上,有下面这行:

<#include "*/footer.ftl">

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

  • /foo/bar/footer.ftl:先在 include 指令所在模版的路径下查找

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

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

<#include> 本地化查找

本地化是指根据当前的设置的语言、国家或方言标识符匹配最优的显示文字。例如:一些网站在中国显示中文,在日本显示日文,在英国显示英文。无论何时模板被请求,期望的本地化都会被指定, 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

上面中,父目录中的 /footer_en_US.ftl 优先子目录 /foo/bar/footer_en.ftl,/foo/bar/footer.ftl 模版,这是因为 /footer_en_US.ftl 同时指定了语言 (en)代码与国家地区(US),比 /foo/bar/footer_en.ftl,/foo/bar/footer.ftl 模版信息更完整、具体。

说说我的看法
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号