申明
本文章主要借鉴于:http://sakyone.iteye.com/blog/524289
介绍
Velocity是一基于java语言的模板引擎,使用这个简单、功能强大的开发工具,可以很容易的将数据对象灵活的与格式化文档组装到一起;
引用
在pom.xml中增加依赖:
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
一个简单的例子
使用Velocity模版引擎,一般通过如下步骤:
1、第一步是要初始化Velocity,Velocity.init().
2、创建一个Context object.
3、将你的数据对象加入到Context对象中.
4、使用Velocity选择一个模板.
5、合并模板和数据导出到输出流.
代码如下:
public class VelocityTest {
/**
* @param args
*/
public static void main(String[] args) {
try {
// 初始化
Velocity.init();
// 取得VelocityContext对象
VelocityContext context = new VelocityContext();
// 向context中放入要在模板中用到的数据对象
context.put("name", new String("Velocity"));
Template template = Velocity.getTemplate("hello.vm");//hello.vm放入工程主目录下
StringWriter writer = new StringWriter();
template.merge(context, writer);
System.out.println(writer.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
hello.vm内容如下:
<html>
<head></head>
<body>
HELLO! $name,Welcome to velocity!
</body>
</html>
程序执行结果,将$name换成了Velocity
<html>
<head></head>
<body>
HELLO! Velocity,Welcome to velocity!
</body>
</html>
进阶介绍
单便和多例
单例模式
前面的例子就是使用的单例模式,这是系统默认的模式, 这样在jvm(应用程序)或web aplication(一个web程序)中只存在一个Velocity engine实例共享使用。. 这对于配置和共享资源来说非常方便. 比如, 这非常适合用于支持 Servlet 2.2+ 的web application中,每一个web app持有它自己的唯一Velocity实例, 它们可以共享templates, a logger等资源. Singleton可以直接通过使用org.apache.velocity.app.Velocity 类。
// 初始化
Velocity.init();
// 取得VelocityContext对象
VelocityContext context = new VelocityContext();
// 向context中放入要在模板中用到的数据对象
context.put("name", new String("Velocity"));
Template template = Velocity.getTemplate("hello.vm");//hello.vm放入工程主目录下
StringWriter writer = new StringWriter();
template.merge(context, writer);
System.out.println(writer.toString());
}
多例模式
在1.2版本以后, 可以在 JVM (or web application.)创建,配置,使用多个Velocity实例;当你希望在同一程序中,对每个实例独立配置时它们的 template directories, loggers等资源时,这是非常方便的. 多实例化时,我们要用到 org.apache.velocity.app.VelocityEngine类.try {
VelocityEngine ve = new VelocityEngine();
ve.init();
// 取得VelocityContext对象
VelocityContext context = new VelocityContext();
// 向context中放入要在模板中用到的数据对象
context.put("name", new String("Velocity"));
Template template = Velocity.getTemplate("hello.vm");
StringWriter writer = new StringWriter();
template.merge(context, writer);
System.out.println(writer.toString());
} catch (Exception e) {
无论是使用单例模式还是使用多例模式,程序员都无须改变程序的结构,而且非常简单的就在两者之间进行转换。
content
1.The Basics
'context' 是Velocity中的一个核心概念, 这是一个从系统的”数据容器(a container of data)”引出的一个常见概念. 这里的context在java程序层和模板视图层(template layer ( or the designer ))之间扮演着一个”数据对象传送者”'(carrier')的角色.
做为程序员,你可以将你程序生成的不同类型的数据对象放入context中,对于视图设计来说,这些对象(包含它们的数据域和命令)将在模板元素中被引用到(references)。一般来说,你将和视图设计者一起决定应用需要哪些数据,可以说,你放入context中的数据对象在这里成为一种”API”,由视图设计者在模板中来访问.因此,在向context中决定放放哪些数据对象时,程序的设计者需要仔细分析视图表现所需的数据内容。
虽然Velocity中你可以创建自己的Context类来支持一些个性化的应用(比如,一个访问,保存LDAP Server服务的context),你可以实现VelocityContext这个己封装较为完务的基类。
VelocityContext对象基本上可满足大多的应用, 我们强烈建议你除非在特别的情况下,否则不要创建自己的Context实现!
VelocityContext用法十分简单,类似于Hashtable class.下面是这个接口提供的两个基本用法:
public Object put(String key, Object value);
public Object get(String key);
很像Hashtable吧,这里的value必须是一个java.lang.Object类(不能是原始类型,像int,boolean), 也不能是null值. 原始类型(Fundamental types like int or float)必须被包装为一个适当对应的Object型.
2.在模板中用#foreach指令支持迭代对象
在放入context前,你对对象有着全面的操作自由. 但就像所有的自由一样, 你必须遵守一些规则,承担一些责任,因此,你必须理解Velocity是如何使用对象的,Velocity的VTL支持多种类型的集合类型(collection types) 使用#foreach().
Object [] 一般对象数组. Velocity将内功能会将它包装成功之为一个实现Iterator interface对象, 这个转换是不需要程序员或视图设计者参与.
java.util.Collection :Velocity会使用他们的标准iterator() 得到一个可以迭代中使用的 Iterator对象,如果你使用自己的实现了Collection interface的对象,要确保它的iterator() 命令返回一个可用的Iterator.
java.util.Map接口对象,Velocity 使用其顶层接口的values() 命令得到一个实现 Collection interface的对象, 应用其iterator()再返回一个Iterator.
java.util.Iterator使用特别注意 : 如果一个Iterator对象被放置到context中,当在模板中有多个 #foreach()指令中,这些#foreach() 将顺序执行,如果第一个调用失败,后面的将阻塞且不能重置.
java.util.Enumeration USE WITH CAUTION : 如同java.util.Iterator一样的道理,Velocity将使用的是一个不能重置('non-resettablity')或者说一个final型的对象.
因此,仅当在不得己的情况下,Iterator and Enumeration 对象才有必要放入context中---也许你有更好的办法不使用他们.
另外一个新引入的概念是context chaining.有时也叫做context wrapping(有点类似与servlet中的chain), 这个高级特性让你可以连结多个独立的Velocity的contexts,以便在template中使用.
例子
传多个参数
代码:
context.put("name", "wangxiaoyu");
context.put("age", "20");
Template template = Velocity.getTemplate("helloCollection.vm");
helloCollection.vm的内容:
<html>
<head></head>
<body>
HELLO! $name,you are only $age years old!
</body>
</html>
传对象
定义一个对象:
public class Person {
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
代码:
Template template = Velocity.getTemplate("helloCollection.vm");
helloCollection.vm的内容:
<html>
<head></head>
<body>
HELLO! $person.name,you are only $person.age years old!
</body>
</html>
传集合
代码:
List<Person> persons = new ArrayList<Person>();
persons.add(new Person("wangxiaoyu", 20));
persons.add(new Person("zhoushuyan", 20));
context.put("persons", persons);
<html>
<body>
#foreach($person in $persons)
<tr bgcolor="#f3f3f3">
<td height="32px">${person.name}</td>
<td height="32px">${person.age}</td>
</tr>
#end
</body>
</html>
代码运行结果:
<html>
<body>
<tr bgcolor="#f3f3f3">
<td height="32px">wangxiaoyu</td>
<td height="32px">20</td>
</tr>
<tr bgcolor="#f3f3f3">
<td height="32px">zhoushuyan</td>
<td height="32px">20</td>
</tr>
</body>
</html>
将content传入另一个content
代码:
// 向context中放入要在模板中用到的数据对象
context1.put("name", "wangxiaoyu");
context1.put("age", "20");
context1.put("duplicate", "I am in context1");
VelocityContext context2 = new VelocityContext(context1);
context2.put("anotherName", "zhoushuyan");
context2.put("anotherAge", "20");
context2.put("duplicate", "I am in context2");
<html>
<body>
$name,$age
$anotherName,$anotherAge
$duplicate
</body>
</html>
代码运行结果:
<html>
<body>
wangxiaoyu,20
zhoushuyan,$anotherAge
I am in context2
</body>
</html>
在模版引擎中可以任意使用context1和context2中的对象,如果context1和context2中都加入了某个对象,则显示后加入的数据。
在servlet中使用velocity