Velocity
网上velovity demo大多简单,这里转载一份比较详细的:
一、Velocity简介
Velocity是一个基于Java的模版引擎。它允许web页面设计者引用Java代码中定义的方法。web设计者能够和Java程序员并行的工作来开发MVC模式的web站点,这意味着web页面设计者能够只关注创建设计良好的站点,而程序员能够只关注编写顶尖的代码。Velocity将Java代码从web页面中分离出来,使得web站点在长期的运行中具有更好的可维护性。
Velocity能够用来创建web页面,SQL,PostScript和其他能够由模版输出的代码。它能够单独使用来生成源代码或者报告,也可以和其他的系统集成。
其实说白了Velocity也就是MVC架构的一种实现,但它更多的是关注在Model和View之间,作为它们的桥梁。对于MVC的最流行架构Struts来说,相信大家都不陌生,很多开发人员已经大量在使用Struts架构,包括IBM的Websphere 5以上的管理平台版本,Struts技术很好的实践了MVC,它有效的减少Java代码在View(Jsp)中的出现,但在Model和View之间还是依靠Struts的Taglib技术来实现,试想如果前台开发的网页设计师对Struts乃至Taglib不熟(相信也挺难熟的,包括后期的维护人员也一样),将会对网页设计师和前台开发工程师的相互协作开发带来很大的难度,现实开发中也还是存在这样事实,网页设计师和前台开发之间的工作或多或少还是存在一定的耦合,怎样最大限度的解决这个难题呢?还是让我们来看看Velocity或者说这个概念吧。
先做一个最简单的Velocity开发例子,让大家看看Velocity是怎样工作的:
1、创建1个文件,文件名为:hellovelocity.vm,即velocity模版(其实和html一样),内容:
<html>
<title>Hello Velocity</title>
<body>
Welcome $name to Javayou.com!
today is $date.
</body>
</html>
2、创建1个java文件,HelloVelocity.java,内容:
package com.javayou.velocity;
import java.io.StringWriter;
import java.util.*;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
/**
* @author Liang.xf 2004-12-14
*/
public class HelloVelocity {
public static void main(String[] args) throws Exception {
//初始化并取得Velocity引擎
VelocityEngine ve = new VelocityEngine();
ve.init();
//取得velocity的模版
Template t = ve.getTemplate("hellovelocity.vm");
//取得velocity的上下文context
VelocityContext context = new VelocityContext();
//把数据填入上下文
context.put("name", "Liang");
context.put("date", (new Date()).toString());
//为后面的展示,提前输入List数值
List temp = new ArrayList();
temp.add("1");
temp.add("2");
context.put("list", temp);
//输出流
StringWriter writer = new StringWriter();
//转换输出
t.merge(context, writer);
System.out.println(writer.toString());
}
}
3.加载需要的包;
4.结果:
<html>
<title>Hello Velocity</title>
<body>
Welcome Liang to Javayou.com!
today is Tue Dec 14 19:26:37 CST 2004.
</body>
</html>
以上是最简单的运行结果,怎么样,知道个大概吧,模版hellovelocity.vm里的2个定义变量$name和$date分别被context.put("name", "Liang")和context.put("date", (new Date()).toString())所设的值替代了。
由此看来业务流程处理包括业务结果基本在model这层全部解决,而view这一层基本只用使用简单的VTL(Velocity Template Language)来展示。这样,Jsp岂不是不用了么?是的,这样的使用模式有点象早前的CGI方式:)由Velocity自动输出代码,并且Velocity在这方面的能力也很强,Turbine里就采用了Velocity来产生很多代码。
在Velocity中,变量的定义都是使用“$”开头的,$作为Velocity的标识符。字母、数字、中划和下划线都可以作为Velocity的定义变量。
此外我们还需要注意的是Velocity特色的变量定义,如:$student.No、$student.Address,它有2层含义:第1种是如果student是hashtable,则将从hashtable中提取key为No和Address的值,另外第2种就是它有可能是调用方法,即上面2个变量将被转换为student.getNo()和student.getAddress()。Velocity对在servlet中的java code返回的值有对象,还可以调用对象的方法,如$ student.getAddress()等等,在此就不一一举例和深入了。
上面的例子只是简单的举例,现在当然不少人已经不满足这样的例子了,实际的应用中我们还常常需要作些选择性展示和列举一些迭代数据,如List列表,当然Velocity(具体来说应该是VTL模版语言)也支持这项功能,此外还支持其他一些常用的展示,如模版内部的变量(如Jsp内的变量),还有强大一些的如创建宏以实现自动化,让我们继续接着往下看吧。
我们还是使用上面的例子,把模版hellovelocity.vm中的内容改为:
#set( $iAmVariable = "good!" )
Welcome $name to Javayou.com!
today is $date.
$iAmVariable
重新执行上面的运行命令,结果:
Welcome Liang to Javayou.com!
today is Tue Dec 14 22:44:39 CST 2004.
good!
可以看得模版中的变量定义为# set开头的语句,不是很难理解,执行后模版中的变量$iAmVariable都转换成定义的值:good!
再来看看简单的选择,把模版hellovelocity.vm中的内容改为:
#set ($admin = "admin")
#set ($user = "user")
#if ($admin = = $user)
Welcome admin!
#else
Welcome user!
#end
执行运行命令,结果:
Welcome user!
可以看到判断语句只是简单的#if ()、#else、#end,不是很复杂。
接着继续来看看迭代数据吧,把模版hellovelocity.vm中的内容改为:
#foreach( $product in $list )
<li>$product</li>
#end
执行运行命令,结果:
<li>1</li>
<li>2</li>
把在例子中预先保存在VelocityContext的List中的值列举了出来,是不是很方便啊?仅仅只是用了#foreach($variable in xx) 而已,如果上面的List换成Hashtable,则可以用下面的语法:
#foreach($key in $hashVariable.keySet() )
<li> $key ‘s value: $ hashVariable.get($key) </li>
#end
一点不觉得这些脚本很复杂。
还有不少人还会问,如果是javabean怎么办?好的,我们增加一个bean:
package com.javayou.velocity;
/**
* @author Liang.xf 2004-12-14
*/
public class Student {
//注意class的属性是public的
public String no = "";
public String address = "";
public Student(String _no, String _address) {
no = _no;
address = _address;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
}
这个Student是实足的javabean,或者说是data bean,常见的用来装载数据的类,然后我们修改HelloVelocity.java,把:
temp.add("1");
temp.add("2");
替换成:
temp.add(new Student("123", "Guangzhou"));
temp.add(new Student("456", "Zhuhai"));
再把hellovelocity.vm的内容改为:
#foreach ($s in $students)
<$velocityCount> Address: $s.address
#end
重新编译和执行运行命令,结果如下:
<1> Address: Guangzhou
<2> Address: Zhuhai
这样把list中Student的数据打印了出来,大功告成!这里用了Velocity的内建变量$velocityCount,指的是默认的列举序号,从1开始,也可以改成0开始,但需要在Velocity.properties中更改,Velocity.properties位于velocity-1.4.jar包内的目录org\\apache\\velocity\\runtime\\defaults 下。
再复杂一些的迭代怎么处理呢?我们看看下面的模版例子就清楚了:
#foreach ($element in $list)
-- inner foreach --
#foreach ($element in $list)
This is $element.
$velocityCount
#end
-- inner foreach --
-- outer foreach --
This is $element.
$velocityCount
-- outer foreach --
#end
看出来了吧,Velocity是支持标签嵌套的,这个可是很强大的功能,这里就不深入演示了,如果有兴趣,自己试试吧