是否可以通过编程方式创建Freemarker宏?

时间:2015-02-12 08:36:01

标签: java freemarker ninjaframework

Freemarker用作忍者Web框架中的默认模板引擎。框架为模板分配了一些默认值,这些默认值在使用忍者Web框架时是全局可用的。我已经为模板创建了一个扩展,它扩展了CSRF-Protection。扩展提供了一个可以在模板中使用的功能,例如

${foo(bar)}

目前需要使用特定参数调用函数,这不是非常直观的。使用宏我可以简化对

的调用
@{foo}

并且用户无需担心传递正确的(例如" bar")参数。但是为了在忍者Web框架中提供这个,我必须以编程方式定义宏。这可能吗?

更新

很抱歉这个混乱。 Meant< @ foo />而不是@ {foo} ...

查看Freemarker文档,我可以更清楚地了解我想要实现的目标:http://freemarker.org/docs/ref_directive_macro.html

就像我上面解释的那样,我将自定义函数传递给模板,让我可以调用

${foo("bar")}

我想要做的是通过像

这样的宏来调用它
@<myMacro/>

但定义的宏像

<#macro myMacro>
  ${foo("bar")}
</#macro> 

不应该在模板中定义,而是以编程方式定义。希望能让它更加清晰。

UPDATE2 / SOLUTION

我最终使用了推荐的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);
    }
}

2 个答案:

答案 0 :(得分:4)

FreeMarker宏调用看起来不像@{...}。这是某种忍者特定的延伸吗?

无论如何,如果你知道数据模型中有bar,那么你的方法可以像Environment.getCurrentEnvironment().getDataModel().get("bar")那样得到它,所以不需要传入它。

此外,知道FTL有两种&#34;子程序&#34;,类似函数的函数和类似指令的函数可能很有用。两者都可以在FTL(#function#macro)和Java(普通Java方法,TemplateMethodModelExTemplateDirectiveModel)中实现。真正的区别在于类似函数的用于计算值,而类似指令的用于将值直接打印到输出(因此绕过自动转义)和副作用。但所有这些都可以达到Environment,所以那里没有区别。

答案 1 :(得分:3)

您可以动态调用宏&#34;#34;。让我们说你有一个宏:

<#macro myMacro>
  ${foo("bar")}
</#macro> 

您可以这样称呼它:

<@myMacro /> 

OR

<@.vars["myMacro"] />

那么你可以做......

<#assign someVar = "myMacro" />

<@.vars[someVar] />