attempt, recover

概要

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

这里:

  • 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 版本中是不存在的。

描述

如果你想让页面成功输出内容,尽管它在页面特定位置发生错误也这样, 那么这些指令就是有用的。如果一个错误在 attempt block 执行期间发生, 那么模板执行就会中止,但是 recover block 会代替 attempt block 执行。 如果在 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 (没有发生错误)块执行时没有输出结果。比如,上面的示例, 发生在"Optional content"之后的失败被打印出来了,而没有在"Ops!"之前输出。 (这是在 attempt block 块内,侵入的输出缓冲的实现,甚至连 flush 指令也会送输出到客户端。)

为了阻止来自上面示例的误解: attempt/recover 不(仅仅)是处理未定义变量(可以使用 不存在变量控制符)。 它可以处理发生在块执行期间的各种类型的错误 (而不是语法错误,这会在执行之前被检测到)。它的目的是包围更大的模板段, 错误可能发生在很多地方。比如,你在模板中有一个部分,来处理打印广告, 但是它不是页面的主要内容,所以你不想你的页面因为一些打印广告 (也可能是短暂的数据库服务器故障)的错误而挂掉。 所以你将整个广告区域放在 attempt block 块中。

在一些环境下,程序员配置 FreeMarker,所以对于特定的错误, 它不会中止模板的执行,在打印一些错误提示信息到输出 (更多内容,请参考 这里...)中之后, 而是继续执行。attempt 指令不会将这些抑制的错误视为错误。

recover block 块中,错误的信息存在 特殊变量 error 中。 不要忘了以点开始引用特殊变量(比如:${.error})。

在模板执行期间发生的错误通常被 日志记录,不管是否发生在 attempt block块中。