随笔-193  评论-715  文章-1  trackbacks-0
作者:张明星  2006.04.12.  MSN:fastzch(at)hotmail.com
题外话:感谢开源精神,如果不是她,我今天可能就不会如此顺利的找到解决问题的方法。

Velocity主要是一个在MVC框架中解决View层问题的框架,其模版功能十分之强大,可以用来做很多事情,据传曾有人用这个来生成程序,还有生成JSP文件等,不过后来也发现这样做的维护开销极大,而且毕竟没有人那多智能。但是在View层做一些改进还是很好的,虽然我并没有拿她来做这样的事,但是从我用她来实现其它的功能便可感受到。
我见过的使用Velocity较好的项目有DLOG4J(中文官方网站为:http://www.javayou.com/main.jspe?cat_id=7),天乙BBS(http://www.laoer.com/)等,大家有兴趣的话可以去看看。

我用Velocity主要是在项目中做为生成各类系统MAIL的template,所以在使用的时候虽然是在WEB应用中,但是并不是做为View层的模版,也不用在web.xml文件中加一堆配置,但是问题随之也产生了。

Velocity读取模版文件的方式采用的是File类,每次都会自动将我们给出的模版的相对路径解析成一个绝对路径,然后再用File类读入,这如果对于一个本地运行的Application来说不会有太大的问题(存在的问题就是模版文件不能一起打包在.JAR文件中,只能放在JAR包的外面,具体位置为与JAR包同一目录下)。这样的方式,对于WEB应用中的相当于资源文件的方式来说简直就是一种灾难,无论是将这些文件放在classes目录下,还是放在lib目录下,都会找不到资源文件。

无奈之下,我只好跟进Velocity的源码,一看究竟。经过一翻追踪,发现模版文件的加载主要由FileResourceLoader这个类来搞定,而且加载模版文件的实现十分繁杂(主要是方法间的调用让人看得极为眼花),最终使用的方法如下:
 1 private InputStream findTemplate(String path, String template)
 2     {
 3         try
 4         {
 5             File file = new File( path, template );
 6             if ( file.canRead() )
 7             {
 8                 return new BufferedInputStream(
 9                     new FileInputStream(file.getAbsolutePath()));
10             }
11             else
12             {
13                return null;
14           }
15         }
16         catch( FileNotFoundException fnfe )
17         {
18             /*
19              *  log and convert to a general Velocity ResourceNotFoundException
20              */
21             return null;
22         }
23     }
在这段code中,关键所在即为 File file = new File( path, template ),所以如果在web应用中运行的话,非把文件放到运行时系统所处的相对路径下才能成功,这对于WEB的部署带来的也是灾难性的后果。
我曾试着在上面这段code的第5行下面用file.getAbsolutePath()得到其绝对路径,作为Application运行的时候,得到的是项目所在的工作目录,而我在Web应用环境下得到的结果却让我大吃一惊,结果居然是:c:\windows\system32(我采用的平台是WinXP+Tomcat5.0.28)。各位看官,到此是不是令你咋舌了?你一定也会觉得这有些不可思议,这样的结果弄得跟系统都变得相关了。

经过一番分析发现有一个极其简单的解决办法(或许我总是喜欢用简单的办法解决问题,这可能也是受XP的影响),将上面的代码改为如下:
 1     private InputStream findTemplate(String path, String template)
 2     {
 3         try
 4         {
 5             File file = new File( path, template );
 6 
 7 //            System.out.println(file.getAbsolutePath());//for test
 8 //            System.out.println(template);
 9             if ( file.canRead() )
10             {
11                 return new BufferedInputStream(
12                     new FileInputStream(file.getAbsolutePath()));
13             }
14             else
15             {
16                // return null;//before modified.
17 
18                    return this.getClass().getClassLoader().getResourceAsStream(template);
19             }
20         }
21         catch( FileNotFoundException fnfe )
22         {
23             /*
24              *  log and convert to a general Velocity ResourceNotFoundException
25              */
26             return null;
27         }
28     }

看看,是不是超级简单。
Compile,打包,搞定!

经过测试,现在无论是将模版文件一起打包到JAR包中还是放到Classes目录下均可。

PS:将模版文件用作View层的Web应用没有测试过,有兴趣的朋友可以帮我测一把。谢谢! 如有错误,欢迎指正。
posted on 2006-04-12 19:54 Robin's Programming World 阅读(3134) 评论(5)  编辑  收藏 所属分类: Java

评论:
# re: Velocity改造心得 2006-04-12 21:15 | BlueDavy
嗯?Velocity本来就有一个ClasspathResourceLoader的配置的....  回复  更多评论
  
# re: Velocity改造心得 2006-04-13 08:48 | zhyiwww
是呀本来就是这样的,不然的话在发布到web之后,回出现找不到文件的异常,
哈哈:)  回复  更多评论
  
# re: Velocity改造心得 2006-04-13 08:50 | zhyiwww
其实你也可以将模版打包进去,然后通过这种方法进行读取,我想应该也是可以的,你可以试一下.
  回复  更多评论
  
# re: Velocity改造心得 2006-04-13 09:09 | Robin's Java World
呵呵,弄了半天看来精力是白费了的。
看来还是应该去好好看看官方的文档。

谢谢大家的指正!  回复  更多评论
  
# re: Velocity改造心得 2007-10-19 17:25 | 行者吴江
public class VelocityTest {

public static void main(String[] args) throws Exception {
VelocityEngine ve=new VelocityEngine();
ve.setProperty(Velocity.RESOURCE_LOADER, "class");
ve.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
ve.init();
Template t=ve.getTemplate("templates/test/test.vm");
StringWriter writer = new StringWriter();
VelocityContext context = new VelocityContext();
t.merge(context, writer);
System.out.println(writer.toString());
}
}  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: