原来的项目中基本都是用 JSP+Tag 来展示内容,有时也有 Jasper Report 做报表,报表也算是一种模板技术,只是有些重量级。看过 Spring 的书籍,都会对 Velocity 和 FreeMaker 有介绍,带动了我对先前看过的 *.vm 文件的研究提上了日程,了解之后,已觉相见恨晚。
下面讲利用 Velocity 怎么更好解决目前项目的一个简单问题:系统在进行支付了支付后,自己按设定的信息模板发送一条短信给责任人。信息模板是:
{单据责任人}:您的 {单据号} 号{单据类型}在 {操作日期} 日已支付
原来的处理方式是在程序中拿到上面定义的模板一次又一次的把前面大括中内容(含大括号)replaceAll() 成实际数据。
如果更多的这种信息模板,处理起来就是不断的重复着代码。
下面介绍利用 Velocity 如何简练的处理上面的问题。Velocity 可在 http://velocity.apache.org/ 下载,下得 velocity-1.5.zip (提笔时版本是1.5),其中有 velocity-1.5.jar和其和依赖包(lib目录中),例子中采用从类路径中加载模板,具体步骤如下:
一:定义模板文件 helloVelocity.vm (要放在类路径下)
1.
## {单据责任人}:您的 {单据号} 号{单据类型}在 {操作日期} 日已支付
2.
${owner}:您的 ${bill} 号${type}在 ${ date } 日已支付
二:加载模板,填充值,输出。 HelloVelocity.java 的代码如下
01.package com.unmi.velocity;
02.
03.import java.io.*;
04.import java.text.*;
05.import java.util.*;
06.
07.import org.apache.velocity.*;
08.import org.apache.velocity.app.*;
09.
10.public class HelloVelocity {
11. public static void main(String[] args) throws Exception {
12. // 配置初始化参数
13. Properties props = new Properties();
14. props.setProperty(Velocity.INPUT_ENCODING, "GBK");
15. props.setProperty(Velocity.RESOURCE_LOADER, "class");
16. props.setProperty("class.resource.loader.class",
17. "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
18.
19. // 初始化并取得Velocity引擎
20. VelocityEngine ve = new VelocityEngine(props);
21.
22. // 取得velocity的模版
23. Template template = ve.getTemplate("helloVelocity.vm");
24.
25. // Template实例的获取方式也可以用下面两行代码
26. // Velocity.init(props);
27. // Template template = Velocity.getTemplate("helloVelocity.vm");
28.
29. // 取得velocity的上下文context
30. VelocityContext context = new VelocityContext();
31.
32. // 把数据填入上下文
33. context.put("owner", "Unmi");
34. context.put("bill", "1000");
35. context.put("type", "报销单");
36. context.put("date", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
37. .format(new Date()));
38.
39. // 输出流,你可以自由控制输出到哪,String、File、Socket 等
40. Writer writer = new PrintWriter(System.out);
41.
42. // 转换输出
43. template.merge(context, writer);
44. writer.flush();
45. }
46.}
以上代码执行结果是在控制台下输出
Unmi:您的 1000 号报销单在 2007-06-04 21:56:13 日已支付
OK,代码应该可以说是十分清晰明了,加载模板->填充值->合并模板输出内容,这就是模板技术要做的事情。
上面介绍的是用 ClasspathResourceLoader 方式加载模板,Velocity 还提供了其他几种 ResourceLoader: DataSourceResourceLoader, FileResourceLoader, JarResourceLoader, StringResourceLoader, URLResourceLoader。由名称我们就能知道它们是从哪加载模板,可在项目中灵活选用适合自己的 ResourceLoader(通过配置 Velocity 引擎的初始化参数)。
Velocity 的默认配置在 velocity.jar 中的 org/apache/velocity/runtime/defaults/velocity.propertis,你可以修改这个文件以适于你的需求,这样就不需要对 VelocityEngine 配置初始化参数 Properties 了。
当然,上面只是一个非常简单的例子,如果仅能完成如此之功能,肯定是用不广泛。所以 Velocity 还提供定义了一种称之为 VTL(Velocity Template Language) 的东西,支持 #if、#foreach、#set、#include、#parse、#macro 等语法能处理你更复杂的数据8028,详细语法参考 Velocity用户手册。可以定义出你想要的功能更完善的模板。他可以作为一个 view 替代 jsp。当然一家定义的 VTL 着实给学习者增加了不少难度,但当你真正喜欢上了,这些都不成问题。
有一个 Velocity Eclipse 插件,可设置 Updates Site 为 http://propsorter.sourceforge.net/veloeclipse 进行下载或更新,方便在Eclipse 中编辑 vm 文件。
你可以想想 Velocity 能为你轻松解决什么问题,如定义模板自动化生成代码,把我某个 Blog 上的所有日志依据模板生成一个 rss.xml 文件就能导入到别的博客中,与 Spring 结合使用。http://velocity.apache.org/ 上的 anakia/texen/velocity-tools 为 Velocity 扩展了更多的功能。
参考与应用:
1. Java的模板引擎Velocity初体验
2. Struts 与 Velocity 的集成
3. Velocity用户手册
4. 模板:velocity和freemarker的比较
5. 邮件发送功能的模板实现
6. Velocity改造心得