是否可以通过编程方式创建 Freemarker 宏?
Posted
技术标签:
【中文标题】是否可以通过编程方式创建 Freemarker 宏?【英文标题】:Is it possible to create a Freemarker macro programmatically? 【发布时间】:2015-04-12 21:50:38 【问题描述】:Freemarker 被用作 ninja web 框架中的默认模板引擎。该框架为使用 ninja web 框架时全局可用的模板分配了一些默认值。我已经为启用 CSRF-Protection 的模板创建了一个扩展。该扩展提供了一个可以在模板中使用的功能,例如
$foo(bar)
目前需要使用特定参数调用函数,这不是很直观。使用宏我可以将这个调用简化为
@foo
并且用户无需担心传递正确的(例如“bar”)参数。但是为了让这个在 ninja web 框架中可用,我必须以编程方式定义一个宏。这可能吗?
更新
很抱歉给您带来了困惑。意思是 而不是 @foo ...
查看 Freemarker 文档,我也许可以更清楚地了解我想要实现的目标:http://freemarker.org/docs/ref_directive_macro.html
就像我上面解释的那样,我将自定义函数传递给模板,使我能够调用
$foo("bar")
我想要做的是通过一个宏来调用它
@<myMacro/>
但是定义的宏喜欢
<#macro myMacro>
$foo("bar")
</#macro>
不应在模板中定义,而是以编程方式定义。希望这能让它更清楚。
更新2/解决方案
我最终使用了推荐的 TemplateDirectiveModel。
public class TemplateEngineFreemarkerAuthenticityTokenDirective implements TemplateDirectiveModel
private String authenticityToken;
public TemplateEngineFreemarkerAuthenticityTokenDirective(Context context)
this.authenticityToken = context.getSession().getAuthenticityToken();
@Override
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException
if (!params.isEmpty())
throw new TemplateException("This directive doesn't allow parameters.", env);
if (loopVars.length != 0)
throw new TemplateException("This directive doesn't allow loop variables.", env);
Writer out = env.getOut();
out.append(this.authenticityToken);
【问题讨论】:
那是<@myMacro/>
,不是@myMacro
。
【参考方案1】:
FreeMarker 宏调用看起来不像 @...
。那是某种忍者特定的扩展吗?
无论如何,如果你知道数据模型中有一个bar
,那么你的方法可以像Environment.getCurrentEnvironment().getDataModel().get("bar")
一样得到它,所以它不需要传入。
此外,了解 FTL 有两种“子例程”可能很有用,一种是函数式的,一种是指令式的。两者都可以在 FTL(#function
、#macro
)和 Java(普通 Java 方法、TemplateMethodModelEx
、TemplateDirectiveModel
)中实现。真正的区别在于,类似函数的用于计算值,而类似指令的用于将值直接打印到输出(因此绕过自动转义)和副作用。但是所有这些都可以到达Environment
,所以那里没有区别。
【讨论】:
感谢您的重播。我认为这不是我想要实现的目标,所以我更新了我的问题。 我的回答基本上是说您可以使用TemplateDirectiveModel
而不是宏。
我确实尝试过使用 TemplateDirectiveModel,但我无法弄清楚如何处理空的 TemplateDirectiveBody(body 为空),因为我只是调用了
有什么要处理的?你想要一个空的身体,所以它应该是null
。【参考方案2】:
您可以“动态地”调用宏。假设你有一个宏:
<#macro myMacro>
$foo("bar")
</#macro>
你可以这样称呼它:
<@myMacro />
或
<@.vars["myMacro"] />
那么你可以这样做......
<#assign someVar = "myMacro" />
<@.vars[someVar] />
【讨论】:
以上是关于是否可以通过编程方式创建 Freemarker 宏?的主要内容,如果未能解决你的问题,请参考以下文章