include

Page Contents

Synopsis

<#include path>
or
<#include path options>

Where:

  • path:要包含的文件的路径;计算结果为字符串的表达式。 (换句话说,它不必是固定的字符串,也可以是类似profile.baseDir + "/menu.ftl"的东西.)

  • options:其中一个或多个:encoding=encodingparse=parse

  • encoding:表达式的计算结果为字符串

    • parse:表达式的计算结果为布尔值(也接受一些字符串值以实现向后兼容)

    • ignore_missing:表达式的计算结果为布尔值

Description

Note:

使用include指令几乎总是一个坏习惯,您应该考虑改用导入指令!即使使用import会增加一些详细信息,但从长远来看,它也会有所回报。参见原因在这里...

您可以使用它将另一个 FreeMarker 模板文件(由path参数指定)插入模板。包含的模板的输出将插入出现include标签的位置。包含文件与包含模板共享变量,就像将其复制粘贴到其中一样。 include指令并没有 true 被包含文件的内容替换,而是每次 FreeMarker 在模板处理过程中每次到达include指令时都处理包含文件。因此,例如,如果includelist循环内,则可以在每个循环中指定不同的文件名。

Note:

该指令不会与 JSP(Servlet)include 混淆,因为它根本不涉及 Servlet 容器,只处理另一个 FreeMarker 模板,而不会“离开” FreeMarker。关于如何进行“ JSP 包含” read this...

path参数可以是相对路径,例如"foo.ftl""../foo.ftl",也可以是绝对路径,例如"/foo.ftl"。相对路径是相对于包含import指令的模板目录的。绝对路径是相对于程序员在配置 FreeMarker 时定义的基础(通常称为“模板的根目录”)。

Note:

这与 FreeMarker 2.1 之前的工作方式不同,后者始终是绝对路径。若要保留旧的行为,请在Configuration对象中启用经典兼容模式。

始终使用/(斜杠)分隔路径组成部分,切勿使用\(反斜杠)分隔。即使您是从本地文件系统加载模板并且它使用反斜杠(例如 Windows 下),也请使用/

Example:

假设/common/copyright.ftl 包含:

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

Then this:

<#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:所包含模板的编码(字符集)。您不应该再使用此选项;如果不同的模板使用不同的编码,则程序员应通过Configuration.setTemplateConfigurations(...) -s(也将覆盖您在此处指定的编码)将编码与模板相关联。如果Configuration.setTemplateConfigurations(...)没有为包含的模板指定编码,则除非您使用此选项指定编码,否则包含的文件将继承顶级模板的编码(字符集)。有效名称的示例:UTF-8,ISO-8859-1,ISO-8859-2,Shift_JIS,Big5,EUC-KR,GB2312.编码名称与 java.io.InputStreamReader 支持的编码名称相同(从 Java API 1.3 开始:IANA Charset Registry 中的 MIME 首选字符集名称)

  • ignore_missing:当true时,如果要包含的模板丢失,则抑制错误,相反<#include ...>将不打印任何内容。当false时,如果缺少模板,模板处理将以错误停止。如果忽略此选项,则默认为false。一种更灵活的方法来处理丢失的模板(例如,当模板丢失时您需要执行某些操作)是使用get_optional_template 特殊变量

Note:

如果ignore_missingtrue,但缺少模板时include指令失败并显示“模板包含失败”错误,这通常是因为您的应用程序使用自定义freemarker.cache.TemplateLoader实现,该实现错误地(针对 API 文档)在findTemplateSource方法中抛出了IOException如果找不到模板,则返回null。如果是这样,则 Java 程序员需要修复该问题。当然,另一种可能性是,由于某些技术问题,确实无法确定模板是否存在,在这种情况下,错误停止是正确的行为。请参阅 Java 堆栈跟踪中的原因IOException以确定是哪种情况。

Example:

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

请注意,可以使用Configuration的“自动包含”设置来自动执行所有模板的常用包含。

Using acquisition

有一个特殊的路径组件,由星号(*)表示。它被解释为“此目录或其任何父目录”。因此,如果位于/foo/bar/template.ftl的模板具有以下行:

<#include "*/footer.ftl">

然后引擎将在以下位置按以下 Sequences 查找模板:

  • /foo/bar/footer.ftl

  • /foo/footer.ftl

  • /footer.ftl

这种机制称为“获取”,使设计人员可以将通常包含的文件放在父目录中,并根据需要在每个子目录的基础上重新定义它们。我们说 include 模板从拥有它的第一个父目录中获取要包含的模板。请注意,您不仅可以在星号右侧指定模板名称,还可以指定子路径。即如果以前的模板改为:

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

那么引擎将在以下位置按以下 Sequences 查找模板:

  • /foo/bar/commons/footer.ftl

  • /foo/commons/footer.ftl

  • /commons/footer.ftl

最后,星号不必是路径的第一个元素:

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

会导致引擎按以下 Sequences 在以下位置查找模板:

  • /foo/bar/commons/footer.ftl

  • /foo/bar/footer.ftl

  • /foo/footer.ftl

  • /footer.ftl

但是,路径中最多可以有一个星号。如果指定更多星号,将找不到该模板。

Localized lookup

语言环境是一种语言和可选的国家/地区或方言标识符(可能还包括其他变体标识符,例如“ MAC”)。每当请求模板时,总是(显式或隐式)指定所需的语言环境,FreeMarke 将尝试查找与该语言环境匹配的模板变体。当模板包含或导入另一个模板时,在内部也会要求一个语言环境,设置locale设置的语言环境(通常是顶层模板的语言环境)。

假设您的模板加载了语言环境en_US,这表示美国英语。当您包含另一个模板时:

<#include "footer.ftl">

实际上,引擎将按以下 Sequences 查找几个模板:

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

引擎将按以下 Sequences 查找这些模板:

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

为什么应使用导入而不是包含

通常,使用导入指令比使用include更好。

乍一看,仅当您拥有一组常用的宏,函数和其他变量并将它们放入模板中以供重用时,导入才合适。但是,人们经常使用include将常见的输出片段(例如页面页脚)插入多个模板。 import指令没有输出,因此显然不是直接替代。但是,将这些输出片段放入宏通常是更好的做法,因为宏可以具有参数,甚至可以嵌套内容。如果执行此操作,则模板中将包含一组宏,您可以import

因此,如果模板中包含宏,函数和其他变量的集合,这就是为什么import通常是更好的选择的原因:

  • 仅在首次请求时才处理导入的模板。为了与include进行比较,假设模板top.ftl包含commons.ftltables.ftl。如果tables.ftl还包含commons.ftl,那么现在commons.ftl将被处理两次。另一方面,第二次导入commons.ftl只会返回第一次导入时已初始化的名称空间。

  • 对于导入,每个导入的模板都有其自己的名称空间。由于它们不只是将所有内容放到公共的共享名称空间中,因此更容易在模板中查看引用的变量或宏/函数的来源。还避免了偶然的名称冲突。

  • 如果您有多个有用的宏/函数/常量集合(例如commons.ftlform.ftlreport.ftl等),并且决定自动导入它们,但是顶层模板通常仅使用其中一些,则可以进行配置自动导入是懒惰的(即,当实际访问其名称空间中的某些内容时,它们会发生)。自动包含是不可能的。

  • import永远不会输出到输出,而include则可能会打印不需要的输出,例如某些空白不会被自动空白删除所删除。