| 作者:张明星? 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应用没有测试过,有兴趣的朋友可以帮我测一把。谢谢! 如有错误,欢迎指正。
Robin's Java World 2006-04-12 19:54
|