Namespaces

Page Contents

运行模板时,您将使用assignmacrofunction伪指令创建了一组变量(可能为空)(请参见previous chapter)。一组类似模板的变量称为 namespace 。在简单的情况下,您仅使用一个名称空间 main 名称空间 。每当您在主模板(宏和函数也是变量,请注意)或其中的模板include-d中定义变量时,即会在其中创建变量。命名空间的关键属性是变量名唯一地标识其中的一个值(即,在同一命名空间中,不能有多个具有相同名称的变量)。

有时您想构建宏,函数和其他变量的可重用集合,我们将其称为“库”。库必须使用其自己的名称空间,以避免意外的名称冲突,这一点很重要。考虑一下,您在该库中可能有很多名称,并且打算在许多模板中使用该库,甚至可能在多个项目中重用它。跟踪另一个模板中使用的库在何处意外地隐藏了数据模型中的变量,或者不应该在模板中分配哪些名称以避免覆盖该库的变量,这变得不切实际。如果您在同一模板中使用了多个库,则将变得更加难以跟踪。因此,您应该为每个库的变量使用一个单独的命名空间。

创建库

这是一个简单的库,其中包含copyright宏和mail字符串:

<#macro copyright date>
  <p>Copyright (C) ${date} Someone. All rights reserved.</p>
</#macro>

<#assign mail = "[email protected]">

将其保存到lib/example.ftl文件(存储模板的目录内)。然后创建一个模板,假设some_web_page.ftl,并在其中使用库:

<#import "/lib/example.ftl" as e>

Some Web page...
<@e.copyright date="1999-2002"/>
${e.mail}
Some Web page...
  <p>Copyright (C) 1999-2002 Someone. All rights reserved.</p>
[email protected]

请注意上面的import directive以及变量e的后续用法。 import与可能已经熟悉的include directive相似,但是它将创建一个空的名称空间,并将在该名称空间中运行lib/example.ftl。因此lib/example.ftl会发现自己处在一个干净的世界中,在该世界中只有数据模型的变量是可见的(和全局变量),并会在此干净的命名空间中创建其两个变量(copyrightmail)。但是您将需要从另一个名称空间(主名称空间)访问这两个变量,因此import指令创建一个哈希变量(在本例中为e)以访问其创建的名称空间。该变量位于import -ing 模板使用的名称空间中,并充当 importlib 的名称空间的窗口。

为了证明两个名称空间是分开的,请考虑以下示例。将lib/example.ftl替换为:

<#macro copyright date>
  <p>Copyright (C) ${date} Someone. All rights reserved.
  <br>Email: ${mail}</p>
</#macro>

<#assign mail = "[email protected]">

some_web_page.ftl与此:

<#import "/lib/example.ftl" as e>
<#assign mail="[email protected]">
<@e.copyright date="1999-2002"/>
${e.mail}
${mail}
<p>Copyright (C) 1999-2002 Someone. All rights reserved.
  <br>Email: [email protected]</p>
[email protected]
[email protected]

如您所见,在some_web_page.ftl中分配的mail变量与在导入的库中分配的mail变量是分开的。

编写导入的名称空间的变量

有时您想在导入的名称空间中创建或替换变量。您可以使用assign指令及其namespace参数来实现:

<#import "/lib/example.ftl" as e>
${e.mail}
<#assign mail="[email protected]" in e>
${e.mail}
[email protected]
[email protected]

命名空间和数据模型

数据模型的变量随处可见。例如,如果数据模型中有一个名为user的变量,则lib/example.ftl将访问它,就像some_web_page.ftl一样:

<#macro copyright date>
  <p>Copyright (C) ${date} ${user}. All rights reserved.</p>
</#macro>

假设user是“ John Doe”:

<#import "/lib/my_test.ftl" as my>
User is: ${user}
<@my.copyright date="1999-2002"/>
User is: John Doe
  <p>Copyright (C) 1999-2002 John Doe. All rights reserved.</p>

不要忘记,当您在该名称空间中时,名称空间中的变量(使用assignmacrofunction指令创建的变量)优先于数据模型的变量。因此,通常,如果库对数据模型变量感兴趣,那么它不会分配给相同的名称。

Note:

在某些不常见的应用程序中,您想要在模板中创建从所有名称空间可见的变量,就像数据模型的变量一样。尽管模板无法更改数据模型,但使用global指令可以实现类似的效果;参见reference

名称空间的生命周期

名称空间由import指令中使用的路径标识(将其标准化为绝对路径后)。如果多次尝试使用等效路径import,它将创建名称空间并仅针对import的第一次调用运行模板。具有等效路径的更高版本的import -s 只会为as关键字之后指定的变量分配相同的名称空间。例如:

<#import "/lib/example.ftl" as e>
<#import "/lib/example.ftl" as e2>
<#import "/lib/example.ftl" as e3>
${e.mail}, ${e2.mail}, ${e3.mail}
<#assign mail="[email protected]" in e>
${e.mail}, ${e2.mail}, ${e3.mail}
[email protected], [email protected], [email protected]
[email protected], [email protected], [email protected]

当您通过ee2e3访问相同的名称空间时,email一次更改了所有名称空间。这样做的实际重要性是,当您在多个模板中导入同一库时,将仅为该库初始化并创建一个命名空间,该命名空间将由所有导入模板共享。

注意,名称空间不是分层的。 import创建另一个名称空间时,您所在的名称空间并不重要。例如,当您在名称空间 N1 中使用import命名空间 N2 时,N2 将不在 N1 内部。 N1 与在主命名空间中import N2 时得到的 N2 相同。

每个模板处理作业都有自己的私有名称空间集。每个模板处理作业都是一个单独的 Universe,仅在呈现主模板时才存在一小段时间,然后其所有填充的名称空间消失。因此,每当我们说“首次调用import”时,我们总是指单个模板处理作业的生命周期内的第一次。

Auto-importing

当您需要在许多模板中一次又一次地导入相同的库时,请知道 Java 程序员(或负责配置 FreeMarker 的人员)可以指定自动导入,这些导入是在所有模板中自动完成的。也可以将自动导入配置为“惰性”(自 FreeMarker 2.3.25 起),这意味着只有在模板中实际使用了导入的库时,才完成自动导入。有关更多详细信息,请参见 Java API 文档:Configuration.setAutoImportsConfiguration.setLazyAutoImports