特殊变量参考

特殊变量是 FreeMarker 引擎本身定义的变量。要访问它们,请使用.variable_name语法。例如,您不能简单地写version;您必须写.version

Note:

从 FreeMarker 2.3.23 开始,对于特殊的变量名称,您可以使用驼峰大小写而不是蛇形大小写,例如dataModel而不是data_model。但是要知道,然后在同一模板中,FreeMarker 将强制使用驼峰式大小写作为模板语言一部分的所有标识符(用户定义的名称不受影响)。

支持的特殊变量是:

  • args(自 2.3.30 起):在macrofunction指令内使用,它返回宏或函数当前调用的所有参数。这允许以统一的方式处理所有参数(例如将其传递给with_args built-in)。更多详细信息:

  • 当在宏中使用时,.args始终是将参数名称 Map 到参数值的哈希。即使使用位置参数调用宏也是如此,因为参数名称是由macro指令声明的。但是在函数内部使用时,.args始终是参数值的序列。那是因为只能使用位置参数来调用函数,因此在function指令内声明的参数名称无关紧要。

    • 对于具有默认值的参数(如<#macro m1 a b=0>中的b),如果宏或函数的调用者省略了该参数(如<@m1 a=1 />),则.args将包含该参数的默认值({'a': 1, 'b': 0})。

    • 如果有一个包罗万象的参数,例如<#macro m2 a, b, others...>中的others,那么.args将直接在 catch-all 参数中包含元素,而不会包含已声明的包罗万象(others)本身。因此,对于<@m2 a=1 b=2 c=3 d=4 />它将是{'a': 1, 'b': 2, 'c': 3, 'd': 4},而不是 {'a': 1, 'b': 2, 'others': {'c':3, 'd': 4}}

    • 如果宏具有包罗万象的参数,而实际的包罗万象的参数也不为空,并且宏在某处使用.args,则只能使用命名参数(如<@m a=1 b=2 />)而不是位置参数(如<@m 1 2 />)来调用它。 。这是因为对于宏.args始终是哈希,但是如果参数是位置参数,则所有参数都不具有名称,因此无法将其放入哈希中。

    • .args会在调用宏或函数时立即初始化,因此不会反映以后在与参数相对应的局部变量上所做的更改。 (但是,如果参数值是可变对象,并且对象本身已突变,则.args将包含已突变的对象.使用local directive设置参数变量不会使对象突变。)

    • .args必须出现在源代码级别的macrofunction指令中,否则是模板解析错误。因此,您不能在动态插入宏或函数的模板片段中使用它(例如通过include directiveeval built-ininterpret built-in)。这是因为macrofunction必须早于调用它就知道它包含.args

    • 对于宏,.args哈希中的元素 Sequences 与在macro指令中声明参数的 Sequences 相同,而不是调用者使用的 Sequences。除外,包罗万象的参数将使用调用者使用的 Sequences。 (对于函数和方法,由于它仅支持位置参数,因此调用方的参数 Sequences 与function指令或 Java 方法中的参数 Sequences 相同,因此毫无疑问.)

  • auto_esc(自 2.3.24 起):布尔值,指示在引用此变量(静态解析)的位置上是否自动转义(基于输出格式)。 不受 escape指令弃用的影响。这仅处理基于输出格式机制的自动转义。

  • caller_template_name(自 FreeMarker 2.3.28 起可用):返回从中调用当前macrofunction的模板的名称(路径)。如果您要解析相对于调用者模板(在这里看到一个例子)的路径,则它最有用。为了更好地实现此目的,如果调用方模板是无名的,则这将是一个空字符串(而不是缺少的值)。如果您不在宏或函数调用中,则读取此变量将导致错误。特别是,用 Java 实现的指令和“方法”将不会影响此变量的值。它仅适用于在模板中实现的宏和函数。 (TemplateDirectiveModel实现可以通过freemarker.core.DirectiveCallPlace对象获得类似的信息.)

  • current_template_name:我们现在所在的模板的名称(自 FreeMarker 2.3.23 起可用)。如果模板是通过 Java(通过new Template(null, ...))即时创建的,而不是通过名称(通过cfg.getTemplate(name, ...))从后备存储中加载的,则可能会丢失(null)。迁移通知:如果用此替换不推荐使用的template_name,请注意,如果模板没有名称,则后者是一个 0 长度的字符串,而不是丢失的(null),因此您可能希望在旧版模板中写入current_template_name!''

  • data_model:可用于直接访问数据模型的哈希。也就是说,您使用global指令所做的变量在此处不可见。

  • error(自 FreeMarker 2.3.1 起可用):该变量可在recover directive主体中访问,该变量存储了从中恢复的错误的错误消息。

  • globals:可用于访问全局可访问变量的哈希:数据模型和使用global指令创建的变量。请注意,使用assignmacro创建的变量不是全局变量,因此在使用globals时它们永远不会隐藏变量。

  • incompatible_improvements(自 FreeMarker 2.3.24 起):当前 FreeMarker 配置的incompatible_improvements setting(以字符串形式)。

  • lang:返回语言环境设置当前值的语言部分。例如,如果.localeen_US,则.langen

  • locale:返回语言环境设置的当前值。这是一个字符串,例如en_US。有关语言环境字符串请参阅设置指令的更多信息。

  • locale_object(自 FreeMarker 2.3.21 起可用):以java.util.Locale对象而不是字符串的形式返回语言环境设置的当前值。当您想将它作为java.util.Locale对象传递给 Java 方法时,它意在代替.locale。 (Locale对象将根据object_wrapper设置值进行包装.是否可以将此值作为Locale对象实际传递给 Java 方法取决于对象包装器,但是让您直接调用 Java 方法的对象包装器不太可能不会支持.)

  • locals:可用于访问局部变量(使用local指令创建的变量以及宏的参数)的哈希。

  • main:可用于访问主要namespace的哈希。请注意,通过此散列“不”可见诸如数据模型变量之类的全局变量。

  • main_template_name:顶级模板的名称(自 FreeMarker 2.3.23 起可用)。 (在 Java 中,这是为其调用Template.process的模板.)如果模板是在 Java 中即时创建(通过new Template(null, ...))而不是通过名称从后备存储中加载(通过new Template(null, ...)),则可能会丢失(null)。 cfg.getTemplate(name, ...))。迁移注意:如果用此替换不推荐使用的template_name,请注意,如果模板没有名称,则后者是一个 0 长度的字符串,而不是丢失的(null),因此您可能希望在旧版模板中写入main_template_name!''

  • namespace:可用于访问当前namespace的哈希。请注意,通过此散列“不”可见诸如数据模型变量之类的全局变量。

  • node(由于历史原因,别名为current_node):您当前正在使用访问者模式(即使用访问,递归等指令)处理的节点。另外,当您使用FreeMarker XML Ant 任务时,它最初存储根节点。

  • now:返回当前日期时间。用法示例:“ Page generated: ${.now}”,“ Today is ${.now?date}”,“ The current time is ${.now?time}”。

  • 返回当前output format的名称。此值永远不会丢失/为空。可能是字符串"undefined",它只是默认输出格式的名称。

  • output_encoding(自 FreeMarker 2.3.1 起可用):返回当前输出字符集的名称。如果封装 FreeMarker 的框架未为 FreeMarker 指定输出字符集,则此特殊变量不存在。 (程序员可以阅读有关字符集问题here...的更多信息)

  • get_optional_template:当您需要包含或导入可能丢失的模板并且需要以某种特殊方式处理这种情况时,将使用此方法。 More details...

  • pass:这是什么都不做的宏。它没有参数。通常在 XML 处理中用作无操作节点处理程序。

  • template_name:*不要使用它,因为使用宏时它的行为很奇怪;请改用current_template_namemain_template_name(请参阅此处的迁移注意事项).*提供主模板的名称,或者,如果正在运行包含或导入的模板,则提供该模板的名称。在调用宏时,它变得相当混乱:宏调用不会更改此特殊变量的值,但是在调用nested时,它将更改为属于当前名称空间的模板的名称。 (自 FreeMarker 2.3.14 起可用.)

  • url_escaping_charset(自 FreeMarker 2.3.1 起可用):如果存在,它将存储应用于 URL 转义的字符集的名称。如果此变量不存在,则表示没有人指定应使用哪种字符集进行 URL 编码。在这种情况下,url built-in使用output_encoding特殊变量指定的字符集进行 URL 编码;自定义机制可能遵循相同的逻辑。 (程序员可以阅读有关字符集问题here...的更多信息)

  • output_format(自 2.3.24 起):引用(静态解析)此变量的位置的输出格式的名称,例如"HTML""XML""RTF""plainText""undefined"等(可用的名称可由程序员扩展,通过registered_custom_output_formats设置.)

  • vars:表达式.vars.foo返回与表达式foo相同的变量。如果由于某些原因必须使用方括号语法,这将很有用,因为该语法仅适用于哈希子变量,因此您需要一个人工父哈希。例如,要读取一个具有使 FreeMarker 混淆的奇怪名称的顶级变量,可以编写.vars["A strange name!"]。或者,要访问具有变量varName给定的动态名称的顶级变量,您可以编写.vars[varName]。请注意,.vars返回的哈希值不支持?keys?values

  • version:以字符串形式返回 FreeMarker 版本号,例如2.2.8。这可以用来检查您的应用程序使用哪个 FreeMarker 版本,但是请注意,此特殊变量在 2.3.0 或 2.2.8 版本之前不存在。非最终版本的版本号在数字后包含短划线和更多信息,例如 2.3.21-nightly_20140726T151800Z。

Using get_optional_template

当您需要包含或导入可能丢失的模板并且需要以某种特殊方式处理这种情况时,将使用此特殊变量。它是一个具有以下参数的方法(因此您打算调用它):

  • 模板的名称(可以是相对名称,也可以是绝对名称),例如"/commonds/footer.ftl";类似于include directive的第一个参数。必填,字符串。

  • 选项的可选哈希,例如{ 'parse': false, 'encoding': 'UTF-16BE' }。有效键是encodingparse。它们的含义与名称相似的include directive参数相同。

此方法返回包含以下条目的哈希:

  • exists:一个布尔值,指示是否找到了模板。

  • include:一个指令,当被调用时,包括模板。调用此指令类似于调用include directive,但是当然您可以省去再次查找模板的麻烦。该指令没有参数,也没有嵌套的内容。如果existsfalse,则此密钥将丢失;否则,此密钥将丢失。稍后再看如何与exp!default 运算符结合使用。

  • import:一种方法,该方法在调用时将导入模板,并返回导入模板的名称空间。调用此方法与调用import指令相似,但是当然您可以省去再次查找模板的麻烦,并且它不会将命名空间分配给任何内容,而只是返回它。该方法没有参数。如果existsfalse,则此密钥将丢失;否则,此密钥将丢失。稍后再看如何与exp!default 运算符一起使用。

调用此方法时(例如.get_optional_template('some.ftl')),如果存在该模板,它将立即加载该模板,但尚未对其进行处理,因此它还没有任何可见的效果。仅当调用返回结构的includeimport成员时,才会处理模板。 (当然,当我们说它加载模板时,它实际上是在模板缓存中查找它,就像include directive一样。)

如果缺少模板,这不是一个错误,但是如果模板确实存在,则是一个错误,但由于模板中的语法错误或某些 I/O 错误而仍然无法加载。

Note:

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

例如,根据some.ftl是否存在,我们要么打印“找到模板:”,然后像<#include 'some.ftl'>那样包含 include 模板,否则我们打印“缺少模板”:

<#assign optTemp = .get_optional_template('some.ftl')>
<#if optTemp.exists>
  Template was found:
  <@optTemp.include />
<#else>
  Template was missing.
</#if>

例如,我们尝试包含some.ftl,但是如果缺少_3,那么我们尝试包含some-fallback.ftl,如果我们也缺少_3,则调用ultimateFallback宏而不是包含任何内容(请注意! -s 在include -s 之后;它们属于到exp!default 运算符):

<#macro ultimateFallback>
  Something
</#macro>

<@(
  .get_optional_template('some.ftl').include!
  .get_optional_template('some-fallback.ftl').include!
  ultimateFallback
) />

该示例的行为类似于<#import 'tags.ftl' as tags>,但是如果缺少tags.ftl,则会创建一个空的tags哈希:

<#assign tags = (.get_optional_template('tags.ftl').import())!{}>