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

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

(一) 自定义指令

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

<@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 自定义指令和函数的更多相关文章

  1. Vue学习笔记十一:按键修饰符和自定义指令(钩子函数)

    目录 padStart:补位 按键修饰符 Vue提供的按键修饰符 自定义按键修饰符 自定义指令 自定义指令的使用 钩子函数 钩子函数参数 使用钩子函数的bingding参数 私有自定义指令 钩子函数的 ...

  2. Vue -自定义指令&钩子函数

    除了核心功能默认内置的指令,Vue也允许注册自定义指令 页面加载后,让文本框自动获取焦点,原生js做法是获取文本框元素后调用focus()方法,但Vue不建议手动操作DOM元素,所以此时要自定义指令 ...

  3. AngularJS笔记--自定义指令

    在前端开发中, 我们会遇到很多地方都会用到同一种类型的控件.AngularJS提供了自定义指令功能,我们可以在指令里面定义特定的html模板.提供给前台html调用. 一. 指令的简单定义.  下面定 ...

  4. 最简单的方式理解Vue的自定义指令与混合

    vue.js 自定义指令 钩子函数:bindinsertedupdatecomponentUpdatedunbind 钩子函数完整实例:html: <div id="hook-argu ...

  5. Vue基础进阶 之 自定义指令

    自定义指令-----钩子函数 自定义指令 除了内置指令,Vue也允许用户自定义指令: 注册指令:通过全局API Vue.directive可以注册自定义指令: 自定义指令的钩子函数: bind: in ...

  6. vue自定义指令VNode详解(转)

    1.自定义指令钩子函数 Vue.directive('my-directive', {bind: function () {// 做绑定的准备工作// 比如添加事件监听器,或是其他只需要执行一次的复杂 ...

  7. Vue_(组件)自定义指令

    Vue.js自定义指令 传送门 自定义指令:除了内置指令,Vue也允许用户自定义指令 注册指令:通过全局API Vue.directive可以注册自定义指令 自定义指令的钩子函数参数:自定义指令的钩子 ...

  8. vue学习(十八)使用自定义指令 为字体渲染颜色

    <div id="app"> //v-color 是自定义的 <input type="text" class="form-cont ...

  9. vue自定义指令实例使用(实例说明自定义指令的作用)

    在写vue项目的时候,我们经常需要对后台返回的数据进行大量的渲染操作,其中就包含了大量的对特殊数据的进一步处理,比如说时间戳.图片地址.特殊数据显示等等特殊数据处理改进. 其实遇到这种情况,通过Vue ...

随机推荐

  1. HDU1232——畅通工程

    #include<stdio.h> ]; int find(int x) //查找根节点 { int r=x; while (pre[r]!=r) //返回根节点 r r=pre[r]; ...

  2. 【hdu6093】Rikka with Number

    多校第五場的題. 首先是一個好數只在某個進制下,不會是在兩個進制下都爲好數. 另外每個進制好數的個數爲d!-(d-1)!,因爲要保證第一位不爲0. 然後就是在臨界進制下有多少個好數的問題,可以變成兩個 ...

  3. 行列式(二):余子式&代数余子式

    目录 按行列展开 \(\Delta\)以下内容主要为<线性代数>的学习笔记 按行列展开 一般来说,低阶行列式的计算比高阶行列式的计算要简单得多,因此考虑用低阶行列式来表示高阶行列式.为此, ...

  4. Toast与Snackbar的那点事

    背景 Toast是Android平台上的常用技术.从用户角度来看,Toast是用户与App交互最基本的提示控件:从开发者角度来看,Toast是开发过程中常用的调试手段之一.此外,Toast语法也非常简 ...

  5. Linux实用命令行

    对于Linux命令,我在学习和使用过程中是有一个循序渐进的过程的.适合小白学习快速使用.大笑 跳转目录:cd +路径 例如:cd /home/workspace 查看某个文件,常用的是查看日志:tai ...

  6. Mybatis笔记二:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)

    错误异常:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.test.dao.N ...

  7. LCA的倍增算法

    LCA,即树上两点之间的公共祖先,求这样一个公共祖先有很多种方法: 暴力向上:O(n) 每次将深度大的点往上移动,直至二者相遇 树剖:O(logn) 在O(2n)预处理重链之后,每次就将深度大的沿重链 ...

  8. oracle 远程登录sqlplus TNS:无监听

    1.将localhost 改成 计算机名 best-PC,或者ip地址 .  我修改成计算机名,因为经常在无线网络和有限网络之间切换 SID_LIST_LISTENER =  (SID_LIST =  ...

  9. 【recording】gdoi2018

    怎么说..虽然感觉其实..不太想写游记.. 但是回来看着桌面上的课本还是忍不住了(想想班里进度就..qwq)还是写一下吧 Day x(x<0) 之前大家溜到首都开心集训了一波然后被虐的很开心.. ...

  10. bzoj4715 囚人的旋律

    4715: 囚人的旋律 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 74  Solved: 48[Submit][Status][Discuss] ...