軟體項目實訓及課程設計指導——如何在Web應用系統表示層開發實現中應用Velocity模板技術
1、分離Web表示層的數據處理和展現邏輯的常見的應用技術
分離Web表示層的數據處理和展現邏輯是目前企業級的Web應用系統開發中表現層組件開發實現中的基本實現目標。為此,軟體應用系統的設計和開發實現人員必須要尋找到一種能夠減少軟體開發人員重複勞動的方法,讓程式設計師將更多的精力放在業務邏輯以及其它更加具有創造力的工作上。
因此,讀者在課程設計的項目開發中,不應該在Web頁面中出現包含大量的伺服器端腳本程序代碼的Web頁面狀況,這樣的Web應用系統在後期的系統維護、升級中都會比較困難。
如下示圖所示的程序代碼示例是不良好的Web表示層程序實現的代碼示例,因為不僅在Web頁面(*.jsp)中包含有大量的Java程序腳本的代碼,而且在JSP頁面中直接訪問資料庫(沒有合理地進行分層設計)和應用System.out.print控制臺信息的輸出語句(此語句只能將信息列印輸出到伺服器主機的系統控制臺上而不能輸出到Web瀏覽器中,前端用戶根本就無法瀏覽到相關的信息)。
希望讀者在學習和閱讀作者的《軟體項目實訓及課程設計指導》系列文章的內容時,重點掌握目前比較主流的分離Web表示層的數據處理和展現邏輯的技術實現方法——比如,採用CSS+Div分離Web表示層數據和表現、應用XML+XSLT技術徹底分離數據和樣式、應用Velocity模板技術實現開發職責分離,並能夠在課程設計的項目開發中應用作者在本系列文章中介紹的各種方法。
當然,分離Web表示層的數據處理和展現邏輯目前其實有多種不同的實現方式,不僅僅局限於作者在上文中所提及和介紹過的方法,比如同樣很優秀的 Freemarker 也獲得了非常廣泛的應用。因此,讀者在項目開發實現中應該要根據項目的具體需要和自己對具體技術實現的熟悉程度合理地選用。
作者在下文中將為讀者介紹如何在J2EE 系統平臺中的Web應用系統表示層開發實現中應用Velocity模板技術。但作者考慮到Velocity模板技術以及隨後幾篇文章中將要介紹的Struts和Struts2應用框架等技術在目前高校的課堂教學中一般都不會涉及,因此部分讀者可能在閱讀本系列文章的內容時對Velocity模板技術和Struts2應用框架會感覺比較陌生,給讀者的學習和理解會帶來一定的難度。
作者建議讀者在課程設計的項目開發中能夠應用Velocity模板技術,經過一段時間的項目開發和應用的實踐,也就能夠慢慢地熟悉和掌握Velocity模板技術和Struts2應用框架等應用技術。
2、什麼是J2EE 系統平臺中的Velocity模板技術
Velocity是Apache 基金會的一個開源的模板引擎項目,其初始開發的主要目標是分離 基於MVC 體系架構設計模式的應用系統的持久化層和業務層,但目前被廣泛地應用於J2EE Web應用系統中的表示層組件開發中。它能夠允許Web開發者在不使用傳統的JSP頁面的應用情況下,可以用 Velocity模板讓HTML頁面也能夠具有動態內容的特性。
如下示圖為Apache Velocity的官方網站頁面中對Velocity模板相關技術特性和應用介紹的文字局部截圖。
讀者可以從Velocity的官方網站上下載Velocity的系統運行包文件和技術參考文檔等系統庫和資料,然後再解包該系統庫的運行包文件,請見下圖所示的下載頁面。
Velocity是一種基於Java系統平臺的模板引擎,它允許軟體應用系統的開發人員使用簡單而強大的模板語言來引用哪些定義在Java程序代碼中的對象。而且Velocity應用具有簡潔的語法和採用類似腳本語言的方式引用目標數據對象。
Velocity模板引擎本身不是採用標準的模型視圖控制器(MVC)體系結構設計,它只是Web應用系統中的「模型組件」和「視圖組件」之間的橋梁。並為Web頁面的前端開發和製作人員提供了一種清晰而又簡單的模板語法,而且模板和程序代碼是分離的。
所以Web應用系統的開發人員可以分別獨立地開發和維護它們,Web前端開發人員可以和後端Java 程序開發人員同步開發一個遵循 MVC體系架構的Web應用系統。而且目前的Velocity 模板引擎也很容易能夠集成到J2EE Web容器的運行環境中——如Servlet容器中,也很容易能夠與Struts應用框架和Struts2應用框架相互集成。
因為Velocity 模板引擎的強大之處在於它嚴格地區分Web應用系統項目開發中的人員職責劃分——頁面開發人員只需要把精力和關注點放在數據的顯示功能實現部分,而Java程式設計師更多地只需要關注如何編程應用系統中的控制層程序和商業業務邏輯、系統中資料庫表中數據的訪問控制和管理等方面的功能實現。
Velocity 模板是一個目前比較流行的JSP頁面技術的替代物,並且能夠實現把 Java 程序代碼從Web頁面中分離出來。
3、Velocity 模板語言VTL
Velocity 模板使用的腳本語言稱為 Velocity 模板語言(VTL,Velocity Template Language),但它和其它形式的腳本語言(如JavaScript等)相比,Velocity 模板語言的語法相對而言比較簡單。
在Velocity 模板語言中提供有變量定義、指令、注釋、對象的引用和各種運算符、宏定義等,也還提供了許多的內置對象。比如下面的代碼語句是設置變量someVarable的值為「Velocity」:#set( $someVarable= "Velocity" )。
在上面的代碼中讀者可以看到很多以「#」和「$」字符開頭的內容,這些都是 Velocity 模板語言的語法。在 Velocity模板語言中所有的關鍵字都是以「#」開頭的,而所有的變量則是以「$」開頭。Velocity 模板語言的語法類似於 JSP 技術中的 JSTL(JSP標準的標籤庫)。
作者考慮到本文章的篇幅有限,在此文中不能詳細地為讀者介紹Velocity 模板語言的語法,讀者有興趣可以參考 和閱讀Velocity 的官方文檔,其中提供了Velocity 語法相關的詳細內容。
4、Velocity模板系統庫中的VelocityServlet組件類
雖然大多數基於Velocity模板的Java應用都是基於J2EE Servlet的Web應用系統,但其實Velocity模板是可以應用於J2SE的應用程式和J2EE Web應用程式的兩種不同的開發環境中。但作者在本文中主要介紹在J2EE Web應用程式的開發環境中如何應用Velocity模板。
但由於Velocity模板只是一個模板引擎,讀者如果需要在J2EE Web應用系統項目中應用Velocity模板,還需要在項目中添加一個HTTP框架以便能夠處理HTTP請求(request)和轉發(response)。
為此,在Velocity模板所提供的系統程序包中,提供有一個VelocityServlet組件類(org.apache.velocity.servlet.VelocityServlet),Web應用系統只需要繼承並擴展它便可以很快地創建一個基於Velocity模板功能處理的Servlet程序,也就是通過繼承VelocityServlet 組件類以產生出自己的Servlet組件。
由於Velocity 模板的系統庫不斷地在更新和升級,如果讀者通過繼承VelocityServlet 組件類以產生出自己的Servlet組件時出現如下的提示信息:「the type VelocityServlet is deprecated」,說明讀者所下載的Velocity 模板系統庫中已經將VelocityServlet升級替換為org.apache.velocity.tools.view.VelocityViewServlet類,讀者只需要將VelocityServlet類修改為VelocityViewServlet類。
如下示圖為Velocity官方網站頁面中對新版本的Velocity 模板系統庫中的VelocityViewServlet類的定義說明局部截圖。
在自己派生出的Servlet組件中可以獲得與HTTP請求相關的request、session與application等對象,從而也可以直接獲得通過Servlet容器保存在這幾個域對象中的值或者返回業務處理後的結果值。
因此,應用Velocity 模板技術可以分離Web應用系統中的業務處理邏輯和數據顯示風格控制邏輯。
5、在Web表示層開發實現中應用Velocity模板的基本步驟
Velocity 的任何模板都可以被VelocityServlet使用、並且能夠部署在伺服器上,也相對比較簡單。只需要採用以下的開發實現步驟:
(1)Web應用系統的開發人員首先通過繼承 org.apache.velocity.servlet.VelocityServlet 類(或者org.apache.velocity.tools.view.VelocityViewServlet類)並派生出自己的Servlet 程序類;
(2) 其次,在所派生出的Servlet 程序類中,重寫並實現其中的一個handleRequest()方法,在 handleRequest() 的方法實現中,從文件或資源(如JAR文件)中取得模板文件並返回該模板;
如下示圖為Velocity官方網站頁面中對handleRequest()的方法定義及功能、返回參數的說明局部截圖。
(3)最後,在重寫的handleRequest() 的方法實現中,添加希望在模板中作為上下文屬性使用的數據或Velocity工具,並且由VelocityServlet向瀏覽器響應輸出——可以由它在向HttpServletResponse的OutputStream 流對象發送之前生成要響應輸出的 HTML標籤。
體現在Web表示層開發實現中應用Velocity模板的基本步驟相關的程序代碼示例如下,讀者可以根據自己的應用項目的需要進行修改和擴展。
public class VelocityServletDemo extends VelocityViewServlet {
@Override
protected Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context ctx) {
/** 在Context上下文環境容器對象實例中存放指定名稱的變量值 */
ctx.put("someVarableName","someVarableValue");
/** 也可以在request域對象實例中存放指定名稱的變量值 */
request.setAttribute("someVarableName","someVarableValue");
…
… 其它的程序代碼,在此省略
…
/** 在業務處理完畢後再 forward轉發到指定模板 */
return getTemplate("myVelocityTemplate.html");
}
}
Velocity 模板文件是文本格式的文件,並且它可以是HTML、XML等類型的文件(上面的程序代碼示例中的模板文件名稱為myVelocityTemplate.html)。但在模板文件中一般包括有如下幾個不同部分的內容:
1)照原樣合併的靜態部分
2)將被要合併的數據替代的佔位符
3)腳本語言中的指示符和指令。
如下頁面代碼為上面程序代碼中最終轉發到的myVelocityTemplate.html模板文件代碼示例,它與標準的HTML頁面差別在於其中包含有黑體標識的數據獲取表達式,如$userName、$userPassword等。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>一個簡單的VelocityWeb應用頁面</title>
</head><body>
<center> <h2>下面為Servlet處理後的結果</h2></center>
<table cellspacing="0" cellpadding="5" width="200" align="center">
<tr><td >用戶名稱</td><td >用戶密碼</td></tr>
<tr><td>$userName</td><td>$userPassword</td></tr>
</table>
</body></html>
另外,myVelocityTemplate.html頁面為靜態的HTML頁面而不是動態的伺服器端的JSP頁面,因此頁面的響應速度將會大大地提高,從而應用Velocity 模板技術的Web頁面可以是非JSP類型的Web頁面——達到動態內容靜態化的應用效果。
6、如何在派生的Servlet程序中向響應輸出的目標頁面傳遞數據
J2EE Web應用系統的開發人員只需要把數據放置到Velocity的上下文對象中(org.apache.velocity.context.Context),然後Velocity引擎使用Velocity上下文對象中的數據、並應用到模板文件中,最後按照模板文件的格式輸出數據。在上面的示例代碼中的如下語句則是在模板文件中獲得保存在Velocity上下文對象中的指定名稱的數據值,然後在表格行中顯示。
<tr><td>$userName</td><td>$userPassword</td></tr>
7、與Velocity模板相關的兩個重要的概念
(1)Velocity模板(Template類)
它是遵守Velocity VTL模板語言的語法規則定義的一個文本格式的文件,該文件採用Velocity語言定義模板文件。比如下面的程序示例代碼是獲得指定文件名稱為VelocityTemplate.vm的模板文件,並指定所應用的編碼格式為中文GB2312編碼:
Template oneTemplateObject =
oneVelocityObject.getTemplate("VelocityTemplate.vm","gb2312");
在默認的情況下,Velocity模板引擎的系統程序會在Web應用系統資源根路徑下搜索*.vm文件,所以開發人員直接將*.vm文件放在Web應用系統資源根路徑下即可(當然,也可以通過配置velocity.properties文件中的配置項目來指定加載的路徑)。
(2) Velocity上下文(VelocityContext類)
它是Velocity模板引擎系統的一個容器,用於保存相關的業務數據。開發人員可以把Velocity模板上下文VelocityContext類看作是導入 Java 對象並在 Velocity 模板內部訪問的一種方法。
比如下面的程序代碼是創建一個VelocityContext類的對象,並在其中保存需要向Web表示層頁面傳遞的參數——參數的名稱為userName,而對應的參數值為「張三」。
VelocityContext oneContextObject = new VelocityContext();
oneContextObject.put("userName", "張三");
因此,只需要通過創建 org.apache.velocity.context.Context 類型的對象實例就可以獲得 Velocity 的上下文VelocityContext對象,然後利用上下文對象中的 put方法,把要導入到模板文件中的對象附加到上下文中。
當然,如果是採用繼承VelocityViewServlet類而派生出自己的Servlet程序類,並在自己的Servlet程序類中重寫handleRequest()方法的方式的程序中,不需要自行再創建出VelocityContext 類的對象實例,而直接應用handleRequest()方法中所攜帶的Context接口類型的對象實例(參看如下示例代碼中的黑體標識的代碼)。
protected Template handleRequest(HttpServletRequest request, HttpServletResponse response, Contextctx) {
}
應用XML+XSLT技術分離Web應用系統中表示層數據和樣式的實例
課程設計指導——如何應用XML+XSLT技術分離Web表示層數據和樣式
課程設計指導—如何應用CSS+Div分離Web表示層數據處理和展現邏輯
如何應用策略設計模式的思想設計通用的資料庫連接類
如何應用觀察者設計模式重構系統中日誌處理功能實現的程序代碼