在Freemarker宏中模拟空参数 [英] Simulate null parameters in Freemarker macros

查看:150
本文介绍了在Freemarker宏中模拟空参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm building a site using Freemarker and have started heavily using macros. I know in Freemarker 2.3 that passing a null value into a macro as a parameter is equivalent to not passing a parameter at all so I've created a global variable called "null" to simulate null checking in my macros:

<#assign null="NUL" />

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

Now in my macros I can do this:

<#maco doSomething param1=null>
  <#if param1 != null>
    <div>WIN!</div>
  </#if>
</#macro>

如果我要传递不是标量的参数,就会出现问题.例如,将列表(在Freemarker中为SimpleSequence)传递给宏,然后对照我的null关键字进行检查,将产生错误:

The problem comes if I want to pass a parameter that isn't a scalar. For instance, passing a List (which in Freemarker is a SimpleSequence) to a macro and checking against my null keyword yields the error:

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

freemarker.template.TemplateException: The only legal comparisons are between two numbers, two strings, or two dates. Left hand operand is a freemarker.template.SimpleSequence Right hand operand is a freemarker.template.SimpleScalar

我看了一下freemarker代码,然后看到了这个问题(ComparisonExpression.isTrue()):

I took a look at the freemarker code and I can see the issue (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);
}

因此,我唯一想到的解决方案是将isClassicCompatible设置为true,我认为这将在两个对象上调用toString()并比较结果.但是,文档特别指出,凡是依赖旧功能的内容都应重写.

So the only solution I can think of is to set isClassicCompatible to true, which I think will call toString() on both objects and compare the result. However, the documentation specifically says anything relying on old features should be rewritten.

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

My quesion is, is there a solution to this that doesn't rely on deprecated features?

推荐答案

null参考在设计上是FreeMarker中的错误.出于您提到的原因,定义一个自定义的null值(它是一个字符串)并不是一个好主意.应改用以下构造:

The null reference is by design an error in FreeMarker. Defining a custom null value - which is a string - is not a good idea for the reasons you mention. The following constructs should be used instead:

  • 宏和函数参数可以具有默认值,因此调用者可以忽略它们
  • 要检查变量是否为null,应使用??运算符:<#if (name??)>
  • 当使用可以为null的变量时,应使用!运算符指定默认值:name!"No name"
  • 要检查序列(或字符串)是否为空,请使用内置的?has_content:<#if (names?has_content)>
  • Macro and function parameters can have a default value, so the callers can omit them
  • To check if a variable is null, you should use the ?? operator: <#if (name??)>
  • When you use a variable that can be null, you should use the ! operator to specify a default value: name!"No name"
  • To check if a sequence (or a string) is empty, use the ?has_content builtin: <#if (names?has_content)>

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

You can specify an empty sequence as default parameter value in a macro, and simply test whether it's empty.

这篇关于在Freemarker宏中模拟空参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆