Velocity之首次研究
與Velocity的第一次見面,是03年,有個(gè)新同事推薦使用,因當(dāng)時(shí)我在做別的項(xiàng)目,也沒怎么仔細(xì)了解,簡(jiǎn)單的知曉類似如模板一類的東西。之后有過幾次接觸,但,都沒花時(shí)間仔細(xì)看,前段時(shí)間,幫朋友做一個(gè)小東西,覺得用個(gè)模板做,會(huì)省很多事,想到Velocity。東西很小,做完了都沒時(shí)間看Velocity,今天正好有時(shí)間,研究研究。Velocity是apache下的一個(gè)開源項(xiàng)目,其網(wǎng)址:http://velocity.apache.org/;下載地址:http://velocity.apache.org/download.cgi,可直接下載源碼,也可通過SVN獲取源碼。
在eclipse中創(chuàng)建一個(gè)web應(yīng)用工程,把Velocity的源碼拷到j(luò)ava資源目錄下,自動(dòng)編譯后,報(bào)幾個(gè)錯(cuò),拷貝下載的Velocity源碼lib目錄下的commons-collections-3.1.jar、oro-2.0.8.jar、commons-lang-2.1.jar這個(gè)三類包到web應(yīng)用工程的lib目錄下即可。
準(zhǔn)備就緒,就寫個(gè)例子跑跑試試。寫一個(gè)hello.vm的模板文件,創(chuàng)建一個(gè)對(duì)應(yīng)的Servlet,就可以運(yùn)行了。兩文件源碼貼出如下:
hello.vm
<html>
<body>
#set($greet = "你好哇!")
Hello!$name, $greet
</body>
</html>
HelloServlet.java<body>
#set($greet = "你好哇!")
Hello!$name, $greet
</body>
</html>
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Properties;
import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.velocity.Template;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.context.Context;
import org.apache.velocity.servlet.VelocityServlet;
public class HelloServlet extends VelocityServlet {
protected Properties loadConfiguration(ServletConfig config)
throws IOException, FileNotFoundException {
Properties p = new Properties();
String path = config.getServletContext().getRealPath("/");
if (path == null) {
path = "/";
}
p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, path);
p.setProperty("runtime.log", path + "velocity.log");
p.setProperty(Velocity.INPUT_ENCODING, "GBK");
p.setProperty(Velocity.OUTPUT_ENCODING, "GBK");
return p;
}
public Template handleRequest(HttpServletRequest request,
HttpServletResponse response, Context ctx) {
Template template = null;
try {
ctx.put("name","Velocity");
template = Velocity.getTemplate("/hello.vm");
} catch (Exception e) {
e.printStackTrace();
}
return template;
}
}
創(chuàng)建servelt要注意的幾個(gè)地方。import java.io.IOException;
import java.util.Hashtable;
import java.util.Properties;
import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.velocity.Template;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.context.Context;
import org.apache.velocity.servlet.VelocityServlet;
public class HelloServlet extends VelocityServlet {
protected Properties loadConfiguration(ServletConfig config)
throws IOException, FileNotFoundException {
Properties p = new Properties();
String path = config.getServletContext().getRealPath("/");
if (path == null) {
path = "/";
}
p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, path);
p.setProperty("runtime.log", path + "velocity.log");
p.setProperty(Velocity.INPUT_ENCODING, "GBK");
p.setProperty(Velocity.OUTPUT_ENCODING, "GBK");
return p;
}
public Template handleRequest(HttpServletRequest request,
HttpServletResponse response, Context ctx) {
Template template = null;
try {
ctx.put("name","Velocity");
template = Velocity.getTemplate("/hello.vm");
} catch (Exception e) {
e.printStackTrace();
}
return template;
}
}
1、新建的Servlet要擴(kuò)展Velocity的VelocityServlet
2、在servlet中要實(shí)現(xiàn) public Template handleRequest(HttpServletRequest request,HttpServletResponse response, Context ctx)
A)把要返回到頁(yè)面上的數(shù)據(jù)放到context中對(duì)應(yīng)到指定鍵值(鍵值名為對(duì)應(yīng)模板中定義的變量名)
B)引入指定模板文件
3、導(dǎo)入配置文件的方法protected Properties loadConfiguration(ServletConfig config),是否實(shí)現(xiàn),是可選的 ,其作用在后面說明。
發(fā)布運(yùn)行后,訪問http://localhost:8080/vt/HelloServelt,就可看到結(jié)果了。
運(yùn)行起來,看到結(jié)果,是覺得很簡(jiǎn)單,其運(yùn)行過程,就要跟蹤看源碼才能知道了。
看源碼,先看的,肯定是VelocityServlet.java。發(fā)現(xiàn)源碼注釋中,這個(gè)類已不推薦使用,推薦使用Velocity的一個(gè)子項(xiàng)目tool中的VelocityViewServlet.java,我沒有當(dāng)tool子項(xiàng)目,就先看這個(gè)“過時(shí)的”實(shí)現(xiàn)。
VelocityServlet.java,擴(kuò)展了HttpServlet,實(shí)現(xiàn)了doGet、doPost、init基本方法,前兩個(gè)方法都直接調(diào)用新實(shí)現(xiàn)的doRequest方法,這些都是很常規(guī)的操作。
doRequest方法做如下幾件事:創(chuàng)建上下文、設(shè)置響應(yīng)內(nèi)容文件類型、獲取模板(調(diào)用每個(gè)請(qǐng)求中的具體實(shí)現(xiàn))、合并數(shù)據(jù)做出響應(yīng)、出錯(cuò)處理及資源清理。看到這兒,整個(gè)請(qǐng)求和響應(yīng)過程很清晰,并沒什么特別的處理。
接下來,看看它的初始化做了些什么事。就做了三件事,超類初始化、自己的初始化、緩存內(nèi)容類型數(shù)據(jù)。自己的初始化,也就是(i)導(dǎo)入配置信息,(ii)根據(jù)配置信息做初始化設(shè)置。導(dǎo)入配置信息,是根據(jù)指定的幾個(gè)地方,獲取配置數(shù)據(jù)(在提供的樣例中,重載了它的獲取配置數(shù)據(jù)的方法,自己靈活的寫入一些配置信息);根據(jù)配置信息做初始化的工作,應(yīng)用單例設(shè)計(jì)模式,保證初始化工作的處理唯一。
VelocityServlet自已的初始化,調(diào)用另一個(gè)類org.apache.velocity.app.Velocity的init( Properties p )方法,就看看Velocity里做了些什么。Velocity里全是靜態(tài)方法。主要有如下幾個(gè)方法:
1、初始化;2、預(yù)演傳入的數(shù)據(jù)(發(fā)現(xiàn)在應(yīng)用中沒有使用,只在單元測(cè)試代碼中引用到);3、合并數(shù)據(jù)和模板;4、設(shè)置/獲取屬性;5、操作信息提示(不過,都不推薦使用了),整個(gè)的看下來,有兩點(diǎn):1、主要的還是初始化和數(shù)據(jù)合并了;2、這個(gè)類只是一個(gè)中轉(zhuǎn)類,所有的方法,最終都是調(diào)另一個(gè)類org.apache.velocity.runtime.RuntimeSingleton的方法。
打開RuntimeSingleton的代碼,看一看,發(fā)現(xiàn)它同Velocity類差不多,類本身不做實(shí)際的處理操作。它與Velocity不同的是,它是申明一個(gè)靜態(tài)的實(shí)例,再調(diào)用這個(gè)實(shí)例,個(gè)別地方(init())加了同步控制。如此處理體現(xiàn)它這個(gè)類的名字--單例,核心的還是這個(gè)靜態(tài)實(shí)例org.apache.velocity.runtime.RuntimeInstance。
到RuntimeInstance,就開始接觸到Velocity的處理核心了。
寫到這兒,突然沒有寫下去的沖動(dòng)了,暫切休息一下。
抽時(shí)間看了一下Velocity子項(xiàng)目tool下的VelocityViewServlet的源碼,比VelocityServlet要實(shí)現(xiàn)的好多了,與struct接合的比較好。
Velocity,不僅僅適合于web應(yīng)用,還可以作生成SQL、XML的模板,內(nèi)容比較多,待一一挖掘。
posted on 2007-05-30 15:49 junctioner 閱讀(2918) 評(píng)論(3) 編輯 收藏 所屬分類: 技術(shù)之路