Freemarker未输入if/else-if值为null


<#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>

这会引发以下错误:

以下内容已评估为null或缺失:===>空

myVar被评估为null缺失——这似乎是我感到困惑的原因;Freemarker不会区分缺失值和现有值,但我想是空值吗?

无论是#if/#else还是任何其他指令调用都无关紧要,因为当发生错误(任何类型的TemplateException,而不仅仅是"缺失值"(时,整个语句都会被跳过。不是可变分辨率,甚至不是整个表达式,而是整个语句。这也是手册和Javadoc所说的,比如:https://freemarker.apache.org/docs/pgui_config_errorhandling.html.因此,templateExceptionHandler设置不用于为缺失值提供默认值。这是为了处理真正错误的情况。比如,有人犯了一个错误,有些事情无法操作。

至于为什么不坐#else呢。当在评估条件时发生错误时,模板引擎无法判断如果开发人员(或任何人(没有犯错误,会采取哪个分支。选择if/else的任何一个分支都是一场赌博。(这甚至不是一场五五开的赌博,因为考虑到输出的真实世界意义,正分支往往是正确的,然而,如果有什么不同的话,人们希望模板引擎将赌注押在else分支上。(因此,希望你至少能打印一些错误指标,它不会选择任何一个分支。但它确实是自动的,因为整个#if/#elseif/#else都是一个大声明。

<#assign myVar = "test"/>
<#if myVar?? && myVar == "test">
A
<#else>
B
</#if>

是的。当变量未定义或为null时,freemarker将引发错误。

常见问题解答中对此进行了解释:为什么FreeMarker对null-s和缺少的变量如此挑剔,以及如何处理它?

这是该框架最初作者的设计选择。如果您不能满足此选择,则可以使用默认值运算符(使用myVar!而不是myVar(,或者使用其他模板框架。

您添加的自定义异常处理程序不会用空字符串替换表达式,而是替换完整的if/else表达式。

最新更新