attempt, recover

Page Contents

Synopsis

<#attempt>
  attempt block
<#recover>
  recover block
</#attempt>

Where:

  • attempt block:包含任何内容的模板块。这将始终执行,但是如果在此期间发生错误,则该块的所有输出都将回滚,并且将执行recover block

  • recover block:包含任何内容的模板块。仅在执行attempt block时发生错误时才执行此操作。您可以在此处等打印错误信息。

recover是必填项。 attempt/recover可以自由嵌套到其他attempt blockrecover block内。

Note:

从 2.3.3 开始,支持此处显示的格式;较早的版本是<#attempt>...<#recover>...</#recover>,仍支持向后兼容。此外,这些指令是在 FreeMarker 2.3.1 中引入的,因此在 2.3 中不存在。

Description

如果您希望页面成功输出,即使页面某部分的输出失败,也可以使用这些指令。如果在执行attempt block时发生错误,则回退attempt block的输出(并记录错误,至少使用默认配置),然后执行recover block,然后在recover block之后正常 continue 执行模板。如果在执行attempt block的过程中未发生错误,则recover block被忽略。一个简单的例子:

Primary content
<#attempt>
  Optional content: ${thisMayFails}
<#recover>
  Ops! The optional content is not available.
</#attempt>
Primary content continued

如果thisMayFails变量不存在(或在该位置发生任何其他错误),则输出为:

Primary content
  Ops! The optional content is not available.
Primary content continued

如果thisMayFails变量存在并且其值为123,则输出为:

Primary content
  Optional content: 123
Primary content continued

attempt block具有全有或全无的语义:要么输出attempt block的全部内容(没有错误时),要么从执行attempt block的结果根本没有输出(当有错误时)。例如,在上面,失败发生在打印了“可选内容:”之后,但在“操作!”之前的输出中仍然没有出现。 (这是通过在attempt block内部积极地缓冲输出来实现的.甚至flush指令都不会将输出发送到 Client 端.)

为了避免上面的示例造成误解:attempt/recover不(仅)用于处理未定义的变量(为此使用缺少值处理程序运算符)。它可以处理执行该块时发生的所有类型的错误(即不是语法错误,这是较早发现的)。它的意思是封装更大的模板片段,在这些片段上可能会出现错误。例如,您的模板中有一部分处理印刷广告,但这不是页面的主要内容,因此您不希望整个页面都掉下来是因为印刷广告时会发生一些错误(例如,因为数据库服务器中断)。因此,您将整个广告打印都放在attempt block中。

在某些环境下,程序员对 FreeMarker 进行了配置,以使其不会因某些错误而中止模板执行,而是 continue 执行(可能在向输出输出一些错误指示符之后再执行)(请参阅here...)。 attempt指令不将抑制的错误视为错误。

recover block内部,该错误的错误消息可用于error special variable。不要忘记对特殊变量的引用以点开头(例如:${.error})。

默认情况下,attempt block内部发生的错误是ERROR级的logged,尽管模板已从中恢复。这是因为attempt并不是通用错误处理程序机制,就像try在 Java 中一样。这是为了减少意外错误对访问者的影响,它可以使页面的仅一部分下降而不是整个页面下降。但这仍然是一个错误,需要操作员注意。 (从 FreeMarker 2.3.27 开始,可以使用attempt_exception_reporter配置设置自定义报告此错误的方式.)