什么是Velocity指令
在Velocity中,#set,#if, #foreach, #elseif, #parse等,以#开头的称之为指令,Velocity内置的这些指令可以用来做赋值,条件判断,循环控制等脚本语言必备的逻辑控制等语句,Velocity的指令是可扩展的,即用户可以根据实际的需要自定义Velocity指令
自定义指令(Directive)的一般步骤
1.定义自定义指令对应的Java代码,这个需要继承自org.apache.velocity.runtime.directive.Directive,覆盖其中的三个抽象方法,
- getName(表示指令的名字,下面的例子中,自定义指令的名字是test)
- getType(表示是行级指令还是块级指令,行级指令解析得到的只有一行,不需要#end指令表明指令结束;而块级指令则需要使用#end显示的指明指令的结束)
- render( public boolean render(InternalContextAdapter context, Writer writer,Node node),用于根据需要,对vm页面进行渲染,以返回期望在页面上显示的值)
2. 在vm文件中使用自定义指令,比如#test,每个指令可以有参数,需要再#test的API文档中清楚说明,例如示例中的#test指定可以包含3个参数
3. 在velocity.properties中指明用户自定义的指令类
指令Java代码
package com.tom.directive
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.directive.Directive;
import org.apache.velocity.runtime.parser.node.Node;
import org.apache.velocity.runtime.parser.node.SimpleNode;
import java.io.IOException;
import java.io.Serializable;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TestDirective extends Directive {
private static final VelocityEngine velocityEngine = new VelocityEngine();
@Override
public String getName() {
return "test";
}
@Override
public int getType() {
return LINE;
}
@Override
public boolean render(InternalContextAdapter context, Writer writer,
Node node) throws IOException, ResourceNotFoundException,
ParseErrorException, MethodInvocationException {
SimpleNode sn = (SimpleNode) node.jjtGetChild(0);
String value = (String) sn.value(context);
sn = (SimpleNode) node.jjtGetChild(1);
Serializable s = (Serializable) sn.value(context);
sn = (SimpleNode) node.jjtGetChild(2);
Object data = sn.value(context);
Map map = new HashMap();
List<String> strings = new ArrayList<String>();
strings.add("MSN");
strings.add("QQ");
strings.add("Gtalk");
map.put("data", strings);
String vel = "#foreach($element in $data) \n<li>$element</li>\n #end";
writer.write(renderTemplate(map, vel));
return true;
}
public static String renderTemplate(Map params, String vimStr) {
VelocityContext context = new VelocityContext(params);
StringWriter writer = new StringWriter();
velocityEngine.evaluate(context, writer, "", vimStr);
return writer.toString();
}
}
velocity代码
<html>
<body>
<div id="123">
#test("Attribute1","Attribute2","Attribute3")
</div>
</body>
</html>
velocity.properties文件的修改
需要把velocity.properites文件放到classpath根目录,在userdirective这个节点添加用户自定义的指令,多个指令类需要用,\进行分割
userdirective=com.tom.directive.DevelopmentDirective,\
com.tom.directive.TestDirective
示例结果
以上代码经Velocity模板引擎解析后,得到的结果是
<html>
<body>
<div id="123">
<li>MSN</li>
<li>QQ</li>
<li>Gtalk</li>
</div>
</body>
</html>