attempt, recover
概要
<#attempt>
attempt block
<#recover>
recover block
</#attempt>
这里:
-
attempt block
:任意内容的模板块。这是会被执行的, 但是如果期间发生了错误,那么这块内容的输出将会回滚, 之后recover block
就会被执行。 -
recover block
: 任意内容的模板块。 这个仅在attempt block
执行期间发生错误时被执行。你可以在这里打印错误信息或其他操作。
recover
是强制的。
attempt
/recover
可以嵌套在其他
attempt block
或
recover block
中。
上面的格式是从 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
块中。