<#if myVar = "test">
A
<#else>
B
<#/if>
如果
myVar
为空/未定义,则 A 和 B 都不会输出。通过在变量后面添加 !
可以解决此问题:
<#if myVar! = "test">
A
<#else>
B
<#/if>
这是故意的吗?因为如果是这样,那就非常令人困惑,我无法想象任何用户会期望它以这种方式运行。这表明
null = "test"
在某种程度上既不正确也不错误。很明显,null = "test"
应该始终被认为是错误的——我错过了什么?
注意:我们已将 Freemarker 配置为用空字符串替换未知变量:
config.setTemplateExceptionHandler((ex, environment, out) ->
{
if (ex instanceof InvalidReferenceException)
{
try
{
out.write("");
}
catch (IOException e)
{
throw new TemplateException("Error while handling template exception.", e, environment);
}
}
else
{
throw ex;
}
});
所以这(至少我认为)最终会是:
<#if "" = "test">
A
<#else>
B
<#/if>
在这种情况下,我希望肯定会输入
else
- 但事实并非如此。
给出这个例子:
<#assign myVar = null/>
<#if myVar == "test">
A
<#else>
B
</#if>
这会引发以下错误:
以下内容已评估为空或缺失: ==> 空
myVar
已被评估为 null 或 缺失——这似乎是我困惑的根源;我猜 Freemarker 不区分缺失值和现有但为空的值?
是否是
#if
/#else
或任何其他指令调用都无关紧要,因为当发生错误时(任何类型的 TemplateException
,而不仅仅是“缺失值”),整个 statement 都会被跳过。不是变量解析,甚至不是整个表达式,而是整个语句。手册和 Javadoc 也是这么说的,请参阅:https://freemarker.apache.org/docs/pgui_config_errorhandling.html。因此,templateExceptionHandler
设置并不是为缺失值提供默认值。它用于处理真正错误的情况。就像,有人犯了一个错误,有些东西无法运行。
至于为什么不继续使用
#else
。当评估条件时发生错误时,模板引擎无法判断如果开发人员(或任何人)没有犯错误,将会采用哪个分支。选择 if
/else
的任何一个分支都是一场赌博。 (这甚至不是一场 50-50 的赌博,因为考虑到输出的现实世界含义,正分支往往是正确的分支,但是,如果有的话,人们希望模板引擎赌在 else
分支上。) ,希望您至少会打印一些错误指示符,它不会选择任何一个分支。但这确实是自动的,因为整个 #if
/#elseif
/#else
事情就是一个大声明。
<#assign myVar = "test"/>
<#if myVar?? && myVar == "test">
A
<#else>
B
</#if>
是的,这是有意的。当变量未定义或为 null 时,freemarker 将引发错误。
常见问题解答中对此进行了解释:为什么 FreeMarker 对 null 和缺失变量如此挑剔,以及如何处理它们?
这是框架最初作者的设计选择。如果您对此选择不满意,可以使用 默认值运算符(使用
myVar!
而不是 myVar
),或使用其他模板框架。
您添加的自定义异常处理程序不会用空字符串替换表达式,而是替换完整的 if/else 表达式。
这样使用
<#if condition 1>
-- do here your work for condition 1
<#else>
<#if condition 2>
-- do here your work for condition 2
<#else>
-- do here your work for else
</#if>
</#if>