在Freemarker宏中模拟空参数

Cam*_*ron 12 freemarker

我正在使用Freemarker构建一个站点并且已经开始大量使用宏.我知道在Freemarker 2.3中,将空值作为参数传递给宏等同于根本不传递参数所以我创建了一个名为"null"的全局变量来模拟我的宏中的空值检查:

<#assign null="NUL" />
Run Code Online (Sandbox Code Playgroud)

现在在我的宏中我可以这样做:

<#maco doSomething param1=null>
  <#if param1 != null>
    <div>WIN!</div>
  </#if>
</#macro>
Run Code Online (Sandbox Code Playgroud)

如果我想传递一个不是标量的参数,问题就来了.例如,将List(在Freemarker中是SimpleSequence)传递给宏并检查我的null关键字会产生错误:

freemarker.template.TemplateException:唯一合法的比较是在两个数字,两个字符串或两个日期之间.左手操作数是freemarker.template.SimpleSequence右手操作数是freemarker.template.SimpleScalar

我看了一下freemarker代码,我可以看到问题(ComparisonExpression.isTrue()):

if(ltm instanceof TemplateNumberModel && rtm instanceof TemplateNumberModel) { 
  ...
}
else if(ltm instanceof TemplateDateModel && rtm instanceof TemplateDateModel) {
  ...
}
else if(ltm instanceof TemplateScalarModel && rtm instanceof TemplateScalarModel) {
  ...
}
else if(ltm instanceof TemplateBooleanModel && rtm instanceof TemplateBooleanModel) {
  ...
}
// Here we handle compatibility issues
else if(env.isClassicCompatible()) {
  ...
}
else {
  throw new TemplateException("The only legal comparisons...", env);
}
Run Code Online (Sandbox Code Playgroud)

所以我能想到的唯一解决方案是将isClassicCompatible设置为true,我认为它会在两个对象上调用toString()并比较结果.但是,文档明确指出应该重写任何依赖旧功能的内容.

我的问题是,是否有一个不依赖于弃用功能的解决方案?

Lau*_*eyn 19

所述null参考是由设计在FreeMarker的错误.由于您提到的原因,定义自定义空值 - 这是一个字符串 - 不是一个好主意.应该使用以下构造:

  • 宏和函数参数可以具有默认值,因此调用者可以省略它们
  • 要检查变量是否是null,您应该使用??运算符:<#if (name??)>
  • 当您使用可变的变量时null,您应该使用!运算符指定默认值:name!"No name"
  • 要检查序列(或字符串)是否为空,请使用?has_content内置函数:<#if (names?has_content)>

您可以在宏中将空序列指定为默认参数值,并只测试它是否为空.

  • @Cameron:您可以使用`?has_content`(http://freemarker.org/docs/ref_builtins_expert.html#ref_builtin_has_content)轻松检查序列是否为空,因此您可以轻松地使用空序列作为默认参数值. (4认同)
  • 我没有提到定义自定义空值是一个坏主意的任何原因,并且在我想将列表作为参数传递并为其指定默认空值的情况下,您的建议都没有帮助我。 (2认同)

Sco*_*pey 9

这就是我所做的,这似乎适用于大多数场景:

默认值应为空字符串,null检查应为?has_content.

<#macro someMacro optionalParam="" >
    <#if (optionalParam?has_content)>
        <#-- NOT NULL -->
    <#else>
        <#-- NULL -->
    </#if>
</#macro>
Run Code Online (Sandbox Code Playgroud)