隨筆-193  評(píng)論-715  文章-1  trackbacks-0
          作者:張明星? 2006.04.12.? MSN:fastzch(at)hotmail.com
          題外話(huà):感謝開(kāi)源精神,如果不是她,我今天可能就不會(huì)如此順利的找到解決問(wèn)題的方法。

          Velocity主要是一個(gè)在MVC框架中解決View層問(wèn)題的框架,其模版功能十分之強(qiáng)大,可以用來(lái)做很多事情,據(jù)傳曾有人用這個(gè)來(lái)生成程序,還有生成JSP文件等,不過(guò)后來(lái)也發(fā)現(xiàn)這樣做的維護(hù)開(kāi)銷(xiāo)極大,而且畢竟沒(méi)有人那多智能。但是在View層做一些改進(jìn)還是很好的,雖然我并沒(méi)有拿她來(lái)做這樣的事,但是從我用她來(lái)實(shí)現(xiàn)其它的功能便可感受到。
          我見(jiàn)過(guò)的使用Velocity較好的項(xiàng)目有DLOG4J(中文官方網(wǎng)站為:http://www.javayou.com/main.jspe?cat_id=7),天乙BBS(http://www.laoer.com/)等,大家有興趣的話(huà)可以去看看。

          我用Velocity主要是在項(xiàng)目中做為生成各類(lèi)系統(tǒng)MAIL的template,所以在使用的時(shí)候雖然是在WEB應(yīng)用中,但是并不是做為View層的模版,也不用在web.xml文件中加一堆配置,但是問(wèn)題隨之也產(chǎn)生了。

          Velocity讀取模版文件的方式采用的是File類(lèi),每次都會(huì)自動(dòng)將我們給出的模版的相對(duì)路徑解析成一個(gè)絕對(duì)路徑,然后再用File類(lèi)讀入,這如果對(duì)于一個(gè)本地運(yùn)行的Application來(lái)說(shuō)不會(huì)有太大的問(wèn)題(存在的問(wèn)題就是模版文件不能一起打包在.JAR文件中,只能放在JAR包的外面,具體位置為與JAR包同一目錄下)。這樣的方式,對(duì)于WEB應(yīng)用中的相當(dāng)于資源文件的方式來(lái)說(shuō)簡(jiǎn)直就是一種災(zāi)難,無(wú)論是將這些文件放在classes目錄下,還是放在lib目錄下,都會(huì)找不到資源文件。

          無(wú)奈之下,我只好跟進(jìn)Velocity的源碼,一看究竟。經(jīng)過(guò)一翻追蹤,發(fā)現(xiàn)模版文件的加載主要由FileResourceLoader這個(gè)類(lèi)來(lái)搞定,而且加載模版文件的實(shí)現(xiàn)十分繁雜(主要是方法間的調(diào)用讓人看得極為眼花),最終使用的方法如下:
          ?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中,關(guān)鍵所在即為?File?file?=?new?File(?path,?template?),所以如果在web應(yīng)用中運(yùn)行的話(huà),非把文件放到運(yùn)行時(shí)系統(tǒng)所處的相對(duì)路徑下才能成功,這對(duì)于WEB的部署帶來(lái)的也是災(zāi)難性的后果。
          我曾試著在上面這段code的第5行下面用file.getAbsolutePath()得到其絕對(duì)路徑,作為Application運(yùn)行的時(shí)候,得到的是項(xiàng)目所在的工作目錄,而我在Web應(yīng)用環(huán)境下得到的結(jié)果卻讓我大吃一驚,結(jié)果居然是:c:\windows\system32(我采用的平臺(tái)是WinXP+Tomcat5.0.28)。各位看官,到此是不是令你咋舌了?你一定也會(huì)覺(jué)得這有些不可思議,這樣的結(jié)果弄得跟系統(tǒng)都變得相關(guān)了。

          經(jīng)過(guò)一番分析發(fā)現(xiàn)有一個(gè)極其簡(jiǎn)單的解決辦法(或許我總是喜歡用簡(jiǎn)單的辦法解決問(wèn)題,這可能也是受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?????}

          看看,是不是超級(jí)簡(jiǎn)單。
          Compile,打包,搞定!

          經(jīng)過(guò)測(cè)試,現(xiàn)在無(wú)論是將模版文件一起打包到JAR包中還是放到Classes目錄下均可。

          PS:將模版文件用作View層的Web應(yīng)用沒(méi)有測(cè)試過(guò),有興趣的朋友可以幫我測(cè)一把。謝謝! 如有錯(cuò)誤,歡迎指正。
          posted on 2006-04-12 19:54 Robin's Programming World 閱讀(3157) 評(píng)論(5)  編輯  收藏 所屬分類(lèi): Java

          評(píng)論:
          # re: Velocity改造心得 2006-04-12 21:15 | BlueDavy
          嗯?Velocity本來(lái)就有一個(gè)ClasspathResourceLoader的配置的....  回復(fù)  更多評(píng)論
            
          # re: Velocity改造心得 2006-04-13 08:48 | zhyiwww
          是呀本來(lái)就是這樣的,不然的話(huà)在發(fā)布到web之后,回出現(xiàn)找不到文件的異常,
          哈哈:)  回復(fù)  更多評(píng)論
            
          # re: Velocity改造心得 2006-04-13 08:50 | zhyiwww
          其實(shí)你也可以將模版打包進(jìn)去,然后通過(guò)這種方法進(jìn)行讀取,我想應(yīng)該也是可以的,你可以試一下.
            回復(fù)  更多評(píng)論
            
          # re: Velocity改造心得 2006-04-13 09:09 | Robin's Java World
          呵呵,弄了半天看來(lái)精力是白費(fèi)了的。
          看來(lái)還是應(yīng)該去好好看看官方的文檔。

          謝謝大家的指正!  回復(fù)  更多評(píng)論
            
          # 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());
          }
          }  回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 周口市| 礼泉县| 昌平区| 岱山县| 广安市| 峨山| 海宁市| 博爱县| 遂昌县| 田阳县| 海林市| 安乡县| 龙海市| 民权县| 辽中县| 开封市| 治县。| 凤冈县| 咸阳市| 那坡县| 江门市| 三门峡市| 蓬莱市| 江山市| 拜泉县| 迁西县| 剑川县| 九龙城区| 芦山县| 武乡县| 富源县| 中方县| 读书| 乐至县| 和龙市| 乐都县| 新余市| 贵定县| 昌平区| 阿尔山市| 旅游|