Freemaker 自定义指令和函数

自定义函数和指令都可以在前台或者后台进行指定。

个人理解:指令的作用,主要是进行页面调整之后进行输出;函数的作用,主要是为了进行运算,返回运算结果供前台展示。

(一) 自定义指令

使用以下格式调用自定义指令:

<@user_def_dir_exp param1=val1 param2=val2 ... paramN=valN/>

定义在前台:

<#macro name param1 param2 ... paramN>

    ...

    <#nested loopvar1, loopvar2, ..., loopvarN>

     ...

    <#return>

    ...

</#macro>

例子:

<#macro test foo bar baaz>

    Test text, and the params: ${foo}, ${bar}, ${baaz}

</#macro>

<#-- call the macro: -->

<@test foo="a" bar="b" baaz=5*5-2/>

输出结果:

Test text, and the params: a, b, 23

定义在后台:

Java程序员可以使用TemplateDirectiveModel接口在Java代码中实现自定义指令。详情可以参加API文档。
注意:
TemplateDirectiveModel在FreeMarker 2.3.11版本时才加入。用来代替快被废弃的TemplateTransformModel。

public class UpperDirective implements TemplateDirectiveModel {

     public void execute(Environment env, Map params,

           TemplateModel[] loopVars, TemplateDirectiveBody body)  throws TemplateException, IOException {

          // 检查参数是否传入

         if (!params.isEmpty()) {

                 throw new TemplateModelException("This directive doesn't allow parameters.");

         }

        if (loopVars.length != 0) {

               throw new TemplateModelException("This directive doesn't allow loop variables.");

        }

       // 是否有非空的嵌入内容

      if (body != null) {

           // 执行嵌入体部分,和FTL中的<#nested>一样,除了

           // 我们使用我们自己的writer来代替当前的output writer.

           body.render(new UpperCaseFilterWriter(env.getOut()));

      } else {

          throw new RuntimeException("missing body");

     }

}

/**

* {@link Writer}改变字符流到大写形式,

* 而且把它发送到另外一个{@link Writer}中。

*/

private static class UpperCaseFilterWriter extends Writer {

        private final Writer out;

       UpperCaseFilterWriter (Writer out) {

            this.out = out;

        }

       public void write(char[] cbuf, int off, int len)

                 throws IOException {

          char[] transformedCbuf = new char[len];

          for (int i = 0; i < len; i++) {

              transformedCbuf[i] = Character.

              toUpperCase(cbuf[i + off]);

         }

        out.write(transformedCbuf);

       }



       public void flush() throws IOException {

           out.flush();

       }

}
例子:

foo

<@upper>

  bar

  <#-- 这里允许使用所有的FTL -->

     <#list ["red", "green", "blue"] as color>

       ${color}

      </#list>

   baaz

</@upper>

wombat

输出结果:

foo

   BAR

      RED

      GREEN

      BLUE

   BAAZ

wombat

(二) 自定义函数

使用类似格式  ${avg(10, 20)}  其中avg为函数名,10,20为传入的参数

定义在前台:

<#function name param1 param2 ... paramN>

   ...

  <#return returnValue>

  ...

</#function>

例子:

<#function avg x y>

    <#return (x + y) / 2>

</#function>

输出结果:

15

定义在后台:

        方法变量在存于实现了TemplateMethodModel接口的模板中。这个接口仅包含一个方法:TemplateModel exec(java.util.List arguments)。当使用方法调用表达式调用方法时,exec方法将会被调用。形参将会包含FTL方法调用形参的值。exec方法的返回值给出了FTL方法调用表达式的返回值。
         TemplateMethodModelEx接口扩展了TemplateMethodModel接口。它没有任何新增的方法。事实上这个对象实现这个标记接口暗示给FTL引擎,形式参数应该直接以TemplateModel-s形式放进java.util.List。否则将会以String-s形式放入List。

public class IndexOfMethod implements TemplateMethodModel {

        public TemplateModel exec(List args) throws TemplateModelException {

               if (args.size() != 2) {

                     throw new TemplateModelException("Wrong arguments");

                }

              return new SimpleNumber(((String) args.get(1)).indexOf((String) args.get(0))); 

       }

}

然后将实例放入到根数据模型中:

root.put("indexOf", new IndexOfMethod());

例子:

<#assign x = "something">

${indexOf("met", x)}

${indexOf("foo", x)}

输出结果:

2

-1

你可能感兴趣的:(freemaker)