<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    迷途書(shū)童

    敏感、勤學(xué)、多思
    隨筆 - 77, 文章 - 4, 評(píng)論 - 86, 引用 - 0
    數(shù)據(jù)加載中……

    使用 Velocity 實(shí)現(xiàn)客戶(hù)端和服務(wù)器端模板

    靈活的模板引擎為 JSP 技術(shù)提供一種沒(méi)有遺產(chǎn)負(fù)擔(dān)的選擇

    developerWorks
    文檔選項(xiàng)
    將此頁(yè)作為電子郵件發(fā)送

    將此頁(yè)作為電子郵件發(fā)送

    將此頁(yè)作為電子郵件發(fā)送

    將此頁(yè)作為電子郵件發(fā)送

    未顯示需要 JavaScript 的文檔選項(xiàng)


    最新推薦

    Java 應(yīng)用開(kāi)發(fā)源動(dòng)力 - 下載免費(fèi)軟件,快速啟動(dòng)開(kāi)發(fā)


    級(jí)別: 初級(jí)

    Sing Li , 作家, Wrox Press

    2004 年 3 月 13 日

    Velocity 是一種通用的、開(kāi)放源代碼的模板解決方案,可以在報(bào)告生成/數(shù)據(jù)轉(zhuǎn)換應(yīng)用程序中獨(dú)立使用,也可以在 MVC 模型框架中作為視圖組件。本文中,Sing Li 介紹了 Velocity,并說(shuō)明如何將其模板處理功能集成到客戶(hù)端獨(dú)立應(yīng)用程序、服務(wù)器端 Web 應(yīng)用程序或者 Web 服務(wù)中。

    在 HTML 或者 XML 這樣的標(biāo)準(zhǔn)表示或交換格式中,文本性數(shù)據(jù)的操作和轉(zhuǎn)換是一種頻繁而且通常非常單調(diào)的活動(dòng),每個(gè)開(kāi)發(fā)人員都會(huì)遇到。模板引擎可以改善這個(gè)過(guò)程,它在模板中保留輸出中的靜態(tài)部分,而動(dòng)態(tài)生成和安排變化的部分。Velocity 是一種高度實(shí)用的、開(kāi)放源代碼的模板引擎,可以方便地集成到其他客戶(hù)端或服務(wù)器端應(yīng)用程序中。

    對(duì)于服務(wù)器端應(yīng)用程序,如果與兼容 Servlet 2.3+ 的 Web 層容器集成,Velocity 為 JSP 技術(shù)提供了一種可行的替代方案,可以強(qiáng)制實(shí)施表示邏輯與應(yīng)用程序業(yè)務(wù)邏輯的清晰劃分。事實(shí)上,Velocity 支持的模板語(yǔ)言非常簡(jiǎn)單,形成的模板也十分清晰,Web 站點(diǎn)設(shè)計(jì)人員和樣式開(kāi)發(fā)人員可以學(xué)習(xí)和維護(hù)這些模板。

    本文中將考察 Velocity 的簡(jiǎn)單模板語(yǔ)言、創(chuàng)建一些模板并將其用于獨(dú)立的客戶(hù)應(yīng)用程序。然后我們將把這個(gè)模板引擎集成到 Struts MVC 框架中作為視圖組件。

    基本模板引擎操作

    基本模板引擎操作非常簡(jiǎn)單。首先看一看清單 1 中的模板:


    清單 1. 基本的 Velocity 模板
    												
    														<html>
    <head>
    <title>A Template Based Page</title>
    </head>
    <body>
    <p>This is a page generated by $generatedBy.</p>
    <p>The customer's name is $customerName.</p>
    
    </body>
    </html>
    
    												
    										

    這個(gè)模板是一個(gè)完整的 HTML 文件。您可以使用文本編輯器或者喜歡的圖形化可視網(wǎng)頁(yè)編輯器創(chuàng)建該文件。創(chuàng)建的簡(jiǎn)易性是基于模板的系統(tǒng)的主要好處和要求。

    當(dāng)模板引擎運(yùn)行時(shí),清單 1 中彩色顯示的部分將被實(shí)際的數(shù)據(jù)替換。獲取數(shù)據(jù)并與模板結(jié)合的過(guò)程稱(chēng)為 合并。看一看清單 2 中的腳本所表示的數(shù)據(jù):


    清單 2. 為模板合并設(shè)置數(shù)據(jù)值
    												
    														#set ($generatedBy = "Velocity")
    #set ($customerName = "John Doe")
    
    												
    										

    現(xiàn)在,如果清單 1 中的模板與清單 2 中的數(shù)據(jù)合并,將得到清單 3 所示的結(jié)果:


    清單 3. 合并到模板中的數(shù)據(jù)
    												
    														<html>
    <head>
    <title>A Template Based Page</title>
    </head>
    <body>
    <p>This is a page generated by Velocity.</p>
    <p>The customer's name is John Doe.</p>
    
    </body>
    </html>
    
    												
    										

    您可能發(fā)現(xiàn),這種特性和字處理程序中的郵件合并功能類(lèi)似。在字處理程序中,信函結(jié)構(gòu)與來(lái)自郵件列表的名稱(chēng)和地址合并。和郵件合并一樣,這種應(yīng)用程序最適用于要合并的數(shù)據(jù)源非常大而且有變化的情況。

    從這個(gè)單純的意義上講,Velocity 是一個(gè)模板引擎。Velocity 的輸出格式僅受文本模板中所能放置的內(nèi)容的限制。包括現(xiàn)在最流行的格式(HTML、XML、SQL,等等)。

    使用 Velocity 模板語(yǔ)言創(chuàng)建模板

    Velocity 模板是文本文件(HTML、XML 等等),其中包括:

    • 照原樣合并的靜態(tài)部分
    • 將被要合并的數(shù)據(jù)替代的占位符
    • 腳本語(yǔ)言中的指示符和指令

    Velocity 模板使用的腳本語(yǔ)言稱(chēng)為 Velocity 模板語(yǔ)言(VTL)。和其他腳本語(yǔ)言相比,VTL 語(yǔ)法相對(duì)而言不是很豐富。任何具有編程背景的人都可以非常快地學(xué)會(huì) VTL。

    占位符與引用

    VTL 中的引用是一個(gè)命名元素,如 $customerName 。引用可以在 Velocity 模板中作為占位符。在模板合并過(guò)程中,這些占位符將被替換成相應(yīng)的文本值,從而形成最終的輸出。比如,在 清單 1 中,我們可以看到使用了兩個(gè) VTL 引用( $generatedBy$customerName )已生成最終輸出結(jié)果。

    變量在 VTL 中是一種引用類(lèi)型。您可以使用 #set() 指示符為變量賦值。清單 4 給出了一些例子:


    清單 4. 變量類(lèi)型的 VTL 引用
    												
    														#set( $this = "Velocity")
    #set( $numericBase = 999 )
    #set( $booleanCondition = true )
    
    
    This page is generated using $this.
    There are ($numericBase + 1) pages in total.
    
    												
    										

    變量名必須從一個(gè)字母開(kāi)始,因此 Velocity 很容易把變量名與模板中的貨幣符號(hào)分開(kāi)(比如, $100 不可能是一個(gè)變量名)。合并操作中所有的變量都被轉(zhuǎn)化成字符串,可能造成一些有趣的現(xiàn)象。看一看清單 4 中用紅色顯示的文本。合并后的輸出如清單 5 所示:


    清單 5. 合并后的模板中帶有數(shù)字值的變量
    												
    														This page is generated using Velocity.
    There are (999 + 1) pages in total.
    
    												
    										

    因?yàn)?$numericBase 在合并操作中被轉(zhuǎn)化成了字符串,因此不會(huì)執(zhí)行算術(shù)操作。因?yàn)?VTL 專(zhuān)門(mén)用于模板操作而非通用的計(jì)算語(yǔ)言,所以只需要支持整數(shù)算術(shù)運(yùn)算(盡管可以使用插件工具進(jìn)行擴(kuò)展)。下面的腳本說(shuō)明了如何利用這種數(shù)學(xué)運(yùn)算能力:

    												
    														#set( $newSum = $numericBase + 1)
    
    There are $newSum pages in total.
    
    												
    										

    該模板合并后相應(yīng)的輸出為:

    												
    														There are 1000 pages in total.
    
    												
    										

    到目前我們處理的還只有標(biāo)量。要?jiǎng)?chuàng)建包含多個(gè)元素的 ArrayList 變量,可以使用如下的語(yǔ)法:

    												
    														#set( $treeList = ["pine", "oak", "maple", "redwood"])
    
    												
    										

    您可以使用 $treeList.get(1) 列表中的第二個(gè)元素。

    賦值以后, $treeList 就是一個(gè)基于 ArrayList 的變量(就像是標(biāo)準(zhǔn) JDK 集合類(lèi)中那樣)。您可以直接使用符號(hào) $treeList.get(n) 訪問(wèn)它的每個(gè)元素,其中的 n 是以 0 為基的 ArrayList 索引。比如,像 清單 6 種紅色顯示的一行所表明的那樣, $treeList.get(1) 用于選擇 ArrayList 中第二項(xiàng),即 oak。這種調(diào)用 ArrayList 類(lèi)方法的語(yǔ)法也可用于調(diào)用其他變量對(duì)象的方法(更多信息請(qǐng)參閱側(cè)欄中的 屬性和方法參考)。

    屬性和方法參考

    除了在模板中設(shè)置變量之外,VTL 引用也可以是對(duì)象屬性或方法。這些對(duì)象是模板可以使用的 Java 類(lèi)(一般通過(guò)上下文,參閱 Velocity 上下文)。

    對(duì)象屬性通過(guò)和 Javabean 類(lèi)似的符號(hào)訪問(wèn)。比如,可以通過(guò) VTL 引用 $customer.LastName 訪問(wèn) $customer 對(duì)象的 LastName 屬性。在幕后,Velocity 使用對(duì)象的訪問(wèn)器方法獲得屬性值(即調(diào)用對(duì)象的 getLastName() 方法)。

    您可以用和屬性訪問(wèn)類(lèi)似的符號(hào)調(diào)用對(duì)象的方法,可以帶參數(shù)列表也可以不帶。比如,可以通過(guò) VTL 引用 $customer.getPhone("mobile") ,調(diào)用 $customer 對(duì)象的 getPhone() 方法獲得移動(dòng)電話號(hào)碼。

    關(guān)于占位符替換的一點(diǎn)說(shuō)明:Velocity 把任何不能識(shí)別的引用作為普通文本打印,如清單 6 中下面突出顯示的兩行(藍(lán)色和紅色)所示:


    清單 6. 占位符置換
    												
    														The second item in the list is $treeList.get(1).
    $notDeclared is an undeclared variable.
    But $!notDeclared is invisible when not declared.
    
    												
    										

    VTL 支持一種靜態(tài)引用符號(hào),以避免呈現(xiàn)不存在的或者 空的 引用。如果使用安靜引用符號(hào),比如 $!notDeclared ,那么 Velocity 將什么也不輸出,而不是輸出完整的引用名。注意變量名前面的“!”表示這是靜態(tài)引用符號(hào)。當(dāng)合并清單 6 中的模板時(shí),兩個(gè)引用都沒(méi)有分配任何值,但是藍(lán)色顯示的引用將原樣顯示,而綠色的一個(gè)則看不到:

    												
    														The second item in the list is oak.
    $notDeclared is an undeclared variable.
    But is invisible when not declared.
    
    												
    										

    選擇性呈現(xiàn)和循環(huán)

    可以使用指示符 #if... #then... #else.... 有條件地呈現(xiàn)模板中特定的部分。清單 7 給出了一個(gè)例子:


    清單 7. 使用 #if、#then 和 #else 有選擇地呈現(xiàn)
    												
    														#if $customer.GoldMember 
     Thank you Mr. $customer.LastName, for flying with us. 
     Your loyal patronage is greatly appreciated.  
     This flight earns you an additional 5000 miles.
    #else
     Thank you for flying with us. 
     Please consider joining our frequent flyer program.
    #endif
    
    												
    										

    在清單 7 的模板中,使用 $customer 對(duì)象的 boolean 屬性 GoldMember 確定在最終輸出中出現(xiàn)哪些信息。對(duì)于金牌顧客,最終輸出中將呈現(xiàn)藍(lán)色顯示的消息;對(duì)于其他顧客,則在最終輸出中呈現(xiàn)綠色顯示的消息。

    模板中經(jīng)常要使用循環(huán)格式化表格或者列表形式的信息。顯示的數(shù)據(jù)通常保存在一個(gè) ArrayList 引用中。在 Velocity 中唯一用于處理重復(fù)循環(huán)的指示符是 #foreach 指示符。清單 8 中的模板通過(guò) $treeList ArrayList 變量演示了 #foreach 指示符的用法。當(dāng)然,也可以使用任何其他可用的集合類(lèi)型的對(duì)象引用,或者返回一個(gè)集合的對(duì)象屬性/方法引用。


    清單 8. 使用 #foreach 循環(huán)
    												
    														<table>
    <tr><td>Tree Name</td></tr>
    #foreach $name in $treeList
    <tr><td>
         $name is a big tree!
    </td></tr>
    #end
    </table>
    
    												
    										

    $treeList 中包含樹(shù)名的列表,清單 8 中的模板合并后的輸出如清單 9 所示:


    清單 9. #foreach 循環(huán)中合并后的輸出
    												
    														<table>
    <tr><td>Tree Name</td></tr>
    <tr><td>
         pine is a big tree!
    </td></tr>
    <tr><td>
         oak is a big tree!
    </td></tr>
    <tr><td>
         maple is a big tree!
    </td></tr>
    <tr><td>
         redwood is a big tree!
    </td></tr>
    </table>
    
    												
    										

    如果從 HTML 瀏覽器中查看,清單 9 當(dāng)然就是一個(gè)包含樹(shù)名的表。

    注意在 #foreach 循環(huán)體內(nèi)有一個(gè)內(nèi)置的計(jì)數(shù)器,可以在 #foreach 指示符循環(huán)體內(nèi)通過(guò) $velocityCounter 引用訪問(wèn)它。默認(rèn)情況下,這個(gè)計(jì)數(shù)器從 1 開(kāi)始,每執(zhí)行一次循環(huán)遞增一次。

    Velocity 中的宏

    Velocity 的一個(gè)主要特性是能夠很容易地定義宏,稱(chēng)為 Velocimacros。宏使您能夠很容易地封裝和重用模板腳本。默認(rèn)情況下,宏保存在 VM_global_library.vm 文件中。比如,考慮清單 10 中名為 #showTree() 的 Velocimacro:


    清單 10. 定義 Velocimacro
    												
    														#macro (showTree)
        #if ($treeList )
            #foreach ($e in $treeList )
                $e 
            #end
        #end
    #end 
    
    												
    										

    您可以調(diào)用 #showTree() Velocimacro 并使用它打印 $treeList ArrayList ―― 如果這個(gè)列表已經(jīng)定義的話。調(diào)用的語(yǔ)法很簡(jiǎn)單,即 #showTree()

    參數(shù)化宏也是可能的。比如,我們可以修改 #showTree() 宏使其用于任何列表,如清單 11 所示:


    清單 11. 帶參數(shù)的 Velocimacro
    												
    														#macro (showList $val)
        #if ($val )
            #foreach ($e in $val )
                $e
            #end
    
        #end
    #end
    
    												
    										

    要使用清單 11 中的宏調(diào)用 $treeList ,我們可以使用 #showList($treeList) 。這兩種情況的輸出都一樣,如清單 12 所示:


    清單 12. Velocimacro 的合并輸出
    												
    														     pine
         oak
         maple
         redwood
    
    												
    										

    其他有趣的 VTL 細(xì)節(jié)

    單行注釋或者行尾注釋從 ## 開(kāi)始,多行注釋則放在 #**# 之間。

    在處理字符串?dāng)?shù)據(jù)時(shí),可以使用雙引號(hào)或單引號(hào)分隔。但是使用雙引號(hào)允許在分隔的字符串 內(nèi)部對(duì) Velocity 引用、指示符甚至 Velocimacros 求值。





    回頁(yè)首


    Velocity 上下文

    您可以把 Velocity 中的上下文看作是導(dǎo)入 Java 對(duì)象,以便在 Velocity 模板內(nèi)部訪問(wèn)的一種方法。這種導(dǎo)入必須在 Java 編碼中明確地完成。和 JSP 代碼或者 JavaScript 不同,不存在“自然的”或“原生方式”使 Velocity 訪問(wèn)任何 Java 對(duì)象。只有明確導(dǎo)入的 Java 對(duì)象才能在 Velocity 模板中使用。

    通過(guò)創(chuàng)建 org.apache.velocity.context.Context 類(lèi)的實(shí)例可以獲得 Velocity 上下文。然后可以使用上下文的 put( key, value) 方法,把將要導(dǎo)入供模板使用的對(duì)象附加到上下文中。key 是一個(gè)字符串名,將在模板中作為可用的引用出現(xiàn)。在產(chǎn)品環(huán)境中,圖形或者 Web 設(shè)計(jì)人員可能負(fù)責(zé)創(chuàng)建和維護(hù)模板,而 Java 開(kāi)發(fā)人員提供可以在模板中訪問(wèn)的對(duì)象集。在這種情況下,設(shè)計(jì)人員和開(kāi)發(fā)人員應(yīng)就對(duì)象集合及其可用的屬性達(dá)成一致并互相協(xié)作。在 Velocity 上下文中附加的屬性將作為主要的接口機(jī)制。

    在模板中訪問(wèn)上下文屬性

    看一看一個(gè)獨(dú)立解析器中包含的示例代碼(請(qǐng)參閱 參考資料)。可以在 \code\src 目錄下找到。比如,在 com.ibm.dvworks.velocity.VelocityParser 類(lèi)中,我們已經(jīng)創(chuàng)建并向 Velocity 上下文中添加了兩個(gè)屬性,如清單 13 所示:


    清單 13. 在 VelocityParser 類(lèi)中創(chuàng)建一個(gè) Velocity 實(shí)例
    												
    														public static void main(String[] args)    {
            VelocityParser velInstance = new VelocityParser(args[0]);
            velInstance.addToContext(  "treeFarm", 
            new String [] { "redwood", "maple", "oak", "pine" });
            velInstance.addToContext( "title", "A Tree Farm");
    velInstance.addToContext( "date", new java.util.Date());
            velInstance.addToContext("fmtr", 
            new org.apache.velocity.app.tools.VelocityFormatter(
                      velInstance.getCurrentContext()));
            velInstance.processTemplate();             
        }
    
    												
    										

    屬性 treeFarm 是一個(gè)關(guān)于樹(shù)名的 ArrayListtitle 屬性是一個(gè)標(biāo)量字符串。一旦附加到上下文中并在合并過(guò)程中傳遞,這些屬性在 Velocity 模板中立刻就變得沒(méi)有用了。清單 14 中的模板使用了這兩個(gè)屬性。您可以在 \code\app\treectx.vm 中找到這個(gè)例子。


    清單 14. 使用 $treeFarm 上下文屬性引用
    												
    														<table>
    <tr><td>$title</td></tr>
    #foreach $name in $treeFarm
    <tr><td>
         $name is a big tree!
    </td></tr>
    #end
    </table>
    
    												
    										

    合并后的輸出如清單 15 所示:


    清單 15. 模板的合并輸出
    												
    														<table>
    <tr><td>A Tree Farm</td></tr>
    <tr><td>
         redwood is a big tree!
    </td></tr>
    <tr><td>
         maple is a big tree!
    </td></tr>
    <tr><td>
         oak is a big tree!
    </td></tr>
    <tr><td>
         pine is a big tree!
    </td></tr>
    </table>
    
    												
    										

    要注意,使用 $treeFarm 上下文屬性引用的方法和前面分析的 $treeList 變量引用一致。

    初始化模板引擎

    分析 VelocityParser 類(lèi)中列出的 main() 方法(參見(jiàn)清單 13)。 VelocityParser 構(gòu)造函數(shù)創(chuàng)建解析器并加載模板,然后增加模板引擎要使用的屬性,最后調(diào)用 processTemplate() 合并數(shù)據(jù)和模板。我們將按照順序依次分析這些方法。

    您可以在 org.apache.velocity.app.Velocity 類(lèi)中使用靜態(tài)方法初始化 Velocity 并加載一個(gè)模板文件。要使用的方法分別為 init()getTemplate() 。對(duì) init() 方法的調(diào)用出現(xiàn)在 VelocityParser 類(lèi)的構(gòu)造函數(shù)中,如清單 16 所示:


    清單 16. 在 VelocityParser 類(lèi)的構(gòu)造函數(shù)中初始化模板引擎
    												
    														      public VelocityParser(String templateFile)  {
            try {
                Velocity.init("velocity.properties");
                mainTemplate = Velocity.getTemplate(templateFile);
             }
             catch( Exception ex ) {
                    System.out.println("Error processing template file: " + templateFile );
              }
          }
    
    												
    										

    在清單 16 中,對(duì) init() 的調(diào)用創(chuàng)建了一個(gè) Velocity 引擎實(shí)例。如果應(yīng)用程序需要?jiǎng)?chuàng)建和管理多個(gè) Velocity 模板引擎實(shí)例,則應(yīng)使用 org.apache.velocity.app.VelocityEngine 類(lèi)。

    上下文鏈

    只要調(diào)用 org.apache.velocity.VelocityContext 類(lèi)的普通構(gòu)造函數(shù)就可以創(chuàng)建直接可用的 Velocity 上下文。

    Velocity 上下文可以 進(jìn)行鏈接(包裝在另一個(gè)上下文內(nèi)部)。如果需要在模板中控制特定對(duì)象引用的可見(jiàn)性和可用性,這樣做非常有用。

    Velocity 將在對(duì)象引用的所有鏈接上下文中搜索屬性。如果遇到重復(fù)的名稱(chēng),則使用最外層的屬性,而內(nèi)部的同名屬性永遠(yuǎn)不會(huì)被訪問(wèn)。

    為了鏈接 Velocity 上下文,要鏈接的上下文應(yīng)該作為參數(shù)傳遞給一個(gè)新上下文的構(gòu)造函數(shù)。清單 17 中 VelocityParser 類(lèi)的重載方法 addToContext() 說(shuō)明了這一點(diǎn):


    清單 17. 使用 addToContext() 方法增加上下文屬性或者上下文鏈接
    												
    														      public void addToContext(String key, Object value) {
              if (mainContext == null)
                  mainContext = new VelocityContext();
               mainContext.put(key, value);
         }
          public void addToContext(VelocityContext chainCtx) {
              mainContext = new VelocityContext(chainCtx);
          }
    
    												
    										

    processTemplate() 方法中,調(diào)用模板的 merge() 方法結(jié)合上下文信息和模板生成輸出流,如清單 18 所示:


    清單 18. 在 processTemplate() 方法中合并模板
    												
    														     public void processTemplate() {
             try {
                BufferedWriter writer = writer = new BufferedWriter(
                    new OutputStreamWriter(System.out));
    
                if ( mainTemplate != null)
                    mainTemplate.merge(mainContext, writer);
                writer.flush();
                writer.close();
            }
            catch( Exception ex )    {
               ex.printStackTrace();
            }
        }
    
    												
    										





    回頁(yè)首


    Velocity 作為獨(dú)立的解析器

    要編譯上述示例獨(dú)立解析器,請(qǐng)使用安裝目錄下 \code\app 中的 compile.bat 文件。要試驗(yàn)該解析器,請(qǐng)使用 process.bat 批處理文件,其中包括:

    												
    														set VEL_HOME=\jdk1.4\vel14rc1
    java -classpath ..\classes;%VEL_HOME%\velocity-dep-1.4-rc1.jar 
    com.ibm.dvworks.velocity.VelocityParser %1 %2 %3
    
    												
    										

    注意,必須同時(shí)在 compile.batprocess.bat 中把環(huán)境變量 VEL_HOME 設(shè)置成安裝 Velocity 的目錄。在 Velocity 發(fā)行包中包含兩類(lèi)不同的 JAR 文件: velocity-dep---?.jar (其中的 --? 是版本號(hào)信息)和 velocity---?.jarvelocity-dep---?.jar 文件包括所有的外部依賴(lài)(Jakarta common-collections、Avalon Logkit 和 ORO 正則表達(dá)式庫(kù)),可以直接使用。如果您的 classpath 中已經(jīng)有一些這樣的庫(kù),您可能希望使用 velocity---?.jar 文件來(lái)代替。如果這些 JAR 組成都不能滿足您的需要,可以很容易地按照需要的方式重新建立 Velocity。Velocity 發(fā)行包中包括一個(gè) ant 腳本,可以為不同的應(yīng)用場(chǎng)景建立 7 種不同的 JAR 配置。

    為了便于上手,Velocity 預(yù)設(shè)了一些默認(rèn)配置屬性,對(duì)于多數(shù)應(yīng)用而言,這都是合理的和可以接受的。這就避免了開(kāi)發(fā)人員從一開(kāi)始就忙于復(fù)雜的配置選項(xiàng),讓他們能馬上體驗(yàn)到這種模板引擎。





    回頁(yè)首


    服務(wù)器上的 Velocity 與 JSP 技術(shù)

    在服務(wù)器端可以使用 Velocity 處理模板和生成的動(dòng)態(tài)內(nèi)容(HTML、XML等)。這和 JSP 技術(shù)的目標(biāo)非常接近。但是,JSP 模型可以毫無(wú)阻礙地訪問(wèn)底層的 Servlet API 和 Java 編程語(yǔ)言。事實(shí)上,為了避免訪問(wèn)這些固有的特性,您在編碼中必須嚴(yán)格約束(只是使用 EL、標(biāo)簽庫(kù)和類(lèi)似的特性)。它基本上是一種在很大程度上開(kāi)放的訪問(wèn)模型。

    拿 Velocity 與之比較。作為一種完全自包含的模板引擎和腳本解釋器,Velocity 擁有完全封閉的模型。任何針對(duì)系統(tǒng)和/或 Java 編程語(yǔ)言的訪問(wèn)都必須明確地啟用。默認(rèn)情況,Velocity 模板中不能訪問(wèn) Java 編程語(yǔ)言的任何方面。這種封閉的模型使 Velocity 能夠提供分離的模板表示層,與任何應(yīng)用程序業(yè)務(wù)邏輯或者數(shù)據(jù)管理代碼清晰地劃分開(kāi)。

    現(xiàn)在讓我們把這種模板引擎與 Tomcat 5 的最新版本集成在一起,看一看 Velocity 在服務(wù)器端的應(yīng)用。





    回頁(yè)首


    與 Tomcat 5 一起部署 Velocity

    Velocity 發(fā)行包帶有一個(gè) org.apache.velocity.servletVelocityServlet 庫(kù)類(lèi),擴(kuò)展它可以很快地創(chuàng)建一個(gè)模板處理 servlet。作為獨(dú)立的客戶(hù)機(jī)應(yīng)用程序測(cè)試的任何模板都可以使用 VelocityServlet 部署在服務(wù)器上。把獨(dú)立的 Velocity 模板轉(zhuǎn)移到 Web 應(yīng)用程序中相對(duì)比較簡(jiǎn)單。只需要以下幾個(gè)步驟:

    Velocity 中的工具

    工具是在模板中可以通過(guò) Velocity 上下文使用的實(shí)用 Java 對(duì)象。雖然可以手工把這些對(duì)象附加到上下文中,但 VelocityViewServlet 工具箱管理器可通過(guò)更加靈活和結(jié)構(gòu)化的方式完成。在模板中一般是通過(guò)調(diào)用工具的方法來(lái)使用它們。 VelocityViewServletVelocityStruts 都提供了非常有價(jià)值的經(jīng)過(guò)測(cè)試的工具,在作為一種視圖技術(shù)部署 Velocity 時(shí)極其有用。

    1. org.apache.velocity.servlet.VelocityServlet 類(lèi)派生一個(gè) Servlet 類(lèi)。
    2. 重寫(xiě)并實(shí)現(xiàn)其中的一個(gè) handleRequest() 方法。
    3. handleRequest() 的實(shí)現(xiàn)中,添加希望在模板中作為上下文屬性使用的數(shù)據(jù)或工具(請(qǐng)參閱側(cè)欄 Velocity 中的工具)。
    4. handleRequest() 的實(shí)現(xiàn)中,從文件或資源(如 JAR 文件)中取得模板并返回它。

    在示例代碼包中, com.ibm.dvworks.velocity.VelTestServlet 就是按照上述步驟創(chuàng)建的一個(gè) servlet。您可以查看 webapps\vservlet\WEB-INF\src 目錄下的代碼。如果改變了這些代碼,一定要使用 compile.bat 批處理文件重新編譯它。

    部署描述符(web.xml 文件)定義了該 servlet 并把它映射到 /vServlet URL 模式中,如清單 19 所示:


    清單 19. 自定義基于 Velocity 的 servlet 的 Tomcat 部署描述符
    												
    														<?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-app
         PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd">
    <web-app>
     <servlet>
        <servlet-name>vServlet</servlet-name>
        <servlet-class>com.ibm.dvworks.velocity.VelTestServlet</servlet-class>
     </servlet>
    
     <servlet-mapping>
        <servlet-name>vServlet</servlet-name>
        <url-pattern>/vServlet</url-pattern>
      </servlet-mapping>
    </web-app>
    
    												
    										

    加載并處理的模板放在 webapps\vServlet 目錄中。在這個(gè)例子中,模板文件稱(chēng)為 variables.vm 。測(cè)試之前一定要保證 velocity-dep---?.jar 文件已經(jīng)放在 webapps\vServlet\WEB-INF\lib 目錄下,然后啟動(dòng) Tomcat 5 并訪問(wèn) http://localhost:8080/vservlet/Servlet URL。

    部署 VelocityViewServlet

    要把模板功能擴(kuò)展到 Web 應(yīng)用程序中,應(yīng)該使用 Velocity 工具集中的 VelocityViewServlet 。Velocity 工具是 Velocity 的一個(gè)子項(xiàng)目(請(qǐng)參閱 參考資料 找到這個(gè) URL 并下載最新的版本)。該 Servlet 為 Velocity 用作一種視圖層技術(shù)提供了更復(fù)雜的支持,既可以與 JSP 技術(shù)聯(lián)合使用也可以代替后者。使用 VelocityViewServlet 可以減少許多冗余代碼,因?yàn)樗峁┝耍?

    • 對(duì)請(qǐng)求對(duì)象和屬性、會(huì)話對(duì)象和屬性以及 servlet 上下文和屬性的直接模板訪問(wèn)
    • 正式的、可外部配置的“工具箱”,可以增加在模板中使用的自定義工具(這里講的工具只是具有公共方法的已編譯的類(lèi))
    • 一個(gè)通用的、經(jīng)過(guò)測(cè)試的、隨時(shí)可用的工具庫(kù)

    要把 VelocityViewServlet 集成到 Web 應(yīng)用程序中,可以看一看示例 velview Web 應(yīng)用程序(在 webapps\velview 目錄中)。該應(yīng)用程序包括本文中所討論的那些模板。此外,它還顯示了請(qǐng)求、會(huì)話以及 servlet 上下文對(duì)象的屬性。集成的步驟如下:

    首先要保證 velocity-tools-view.jar 文件在應(yīng)用程序的 lib 目錄中。當(dāng)然,這個(gè) velocity JAR 文件也應(yīng)該在那兒。

    在部署描述符 web.xml 文件中,包括 VelocityViewServlet 。初始化參數(shù)是一個(gè)工具箱描述 XML 文件。該 servlet 映射為處理所有擴(kuò)展名為 .vm 的文件,如清單 20 所示:


    清單 20. VelocityViewServlet 的 Tomcat 部署描述符(web.xml)
    												
    														<?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-app
         PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd">
    <web-app>
      <servlet>
        <servlet-name>velocityView</servlet-name>
        <servlet-class>org.apache.velocity.tools.view.servlet.VelocityViewServlet</servlet-class>
        <init-param>
          <param-name>org.apache.velocity.toolbox</param-name>
          <param-value>/WEB-INF/toolbox.xml</param-value>
        </init-param>
      </servlet>
      <servlet-mapping>
        <servlet-name>velocityView</servlet-name>
        <url-pattern>*.vm</url-pattern>
      </servlet-mapping>
    </web-app>
    
    												
    										

    該例子的工具箱描述符(toolbox.xml)文件中,包含了兩個(gè)來(lái)自 Velocity 工具庫(kù)的通用工具可以在模板 DateToolMathTool 中訪問(wèn)。這兩個(gè)工具使我們能夠格式化日期和時(shí)間信息,并在模板中執(zhí)行浮點(diǎn)運(yùn)算,如清單 21 所示:


    清單 21. 包括 DateTool 和 MathTool 的工具箱描述符
    												
    														<?xml version="1.0"?>
    <toolbox>
      <tool>
       <key>date</key>
       <scope>application</scope>
       <class>org.apache.velocity.tools.generic.DateTool</class>
     </tool>
    <tool>
      <key>math</key>
      <scope>application</scope>
      <class>org.apache.velocity.tools.generic.MathTool</class>
    </tool>
    ...
    
    												
    										

    VelocityViewServlet 中有一組常用的標(biāo)準(zhǔn)工具,如表 1 所示:

    表 1. VelocityViewServlet 中的標(biāo)準(zhǔn)工具

    工具名 描述
    LinkTool 處理 URI。該工具經(jīng)常會(huì)用到,如果在模板中創(chuàng)建可點(diǎn)擊的鏈接就要用到該工具,可以生成依賴(lài)于上下文的 URI 部分。
    CookieTool 使模板能夠創(chuàng)建或訪問(wèn)瀏覽器緩沖的 cookie。
    ParameterParser 簡(jiǎn)化后面收到的請(qǐng)求參數(shù)的解析。

    還有兩個(gè)高度專(zhuān)門(mén)化的、不那么常用的工具,如表 2 所示:

    表 2. 專(zhuān)門(mén)的 VelocityViewServlet 工具

    工具名 描述
    ViewRenderTool 使模板能夠解析包含 VTL 的字符串。
    AbstractSearchTool 提供了一種骨架工具(必須使用自定義的 Java 代碼來(lái)擴(kuò)展),以便實(shí)現(xiàn)在線搜索和搜索結(jié)果分頁(yè)。

    您可以使用 http://localhost:8080/velview/variables.vm URL 測(cè)試 velview 應(yīng)用程序。您應(yīng)該打開(kāi)模板源代碼看一看所用的 Velocity 引擎、 LinkToolCookieTool





    回頁(yè)首


    與 Struts 框架的互操作

    Struts 是一種構(gòu)造基于 MVC 模型的框架的流行 Web 應(yīng)用程序。Struts 默認(rèn)的視圖組件技術(shù)是 JSP 技術(shù)。但是,可以很容易把 Velocity 集成進(jìn)來(lái)作為視圖組件。圖 1 說(shuō)明了 Velocity 的這種具體應(yīng)用:


    圖 1. Velocity 與 Struts MVC 框架集成

    重要的是要看到,在這種結(jié)合中 Velocity 并沒(méi)有代替 JSP 技術(shù)。相反,JSP 技術(shù)和 Velocity 模板可以協(xié)同工作。集成 Velocity 需要配置 VelocityViewServlet 以便處理 .vm 模板,就像 部署 VelocityViewServlet 部分所講的那樣。這意味著.jsp 文件將繼續(xù)由容器(即 Tomcat 5 中的 Jasper)處理,而任何 .vm 模板則傳遞給 Velocity。

    Velocity Tools 子項(xiàng)目中的 VelocityStruts 組件(請(qǐng)參閱 參考資料)包含集成 Velocity 與 Struts 的所有功能。 VelocityStruts 提供了一組專(zhuān)用的 Velocity 工具,用于訪問(wèn) Struts 專(zhuān)有的資源和 Velocity 模板中的信息。表 3 列出了最常用的工具:

    表 3. 用于 VelocityStruts 集成的工具

    工具名 描述
    StrutsLinkTool 針對(duì) Struts 的 LinkTool 專(zhuān)用版本,提供了 setAction()setForward() 訪問(wèn)預(yù)先配置的活動(dòng)映射。
    FormTool 訪問(wèn) Struts 的表單 beans。
    ErrorsTool 處理 Struts 錯(cuò)誤消息,包括對(duì)國(guó)際化的支持。
    MessageTool 提供對(duì) Struts 國(guó)際化支持的訪問(wèn),尤為特別的是依賴(lài)于語(yǔ)言的消息資源。

    還有一組工具專(zhuān)用于 Struts 1.1 中的新特性,如表 4 所示:

    表 4. 專(zhuān)用的 Struts 1.1 訪問(wèn)工具

    工具名 描述
    SecureLinkTool 用于 Struts 1.1 的安全鏈接(SSL)擴(kuò)展。
    ActionMessagesTool 提供對(duì) Struts 1.1 新對(duì)象 ActionMessages 的訪問(wèn)。
    TilesTool 提供對(duì) Struts 1.1 Tiles 擴(kuò)展支持的訪問(wèn)。
    ValidatorTool 提供對(duì) Struts 1.1 Validator 擴(kuò)展的訪問(wèn),生成代碼驗(yàn)證表單輸入字段。

    webapps\struts-example 目錄中可以找到一個(gè)例子,使用 Struts 而非 JSP 技術(shù)創(chuàng)建 Struts 頁(yè)面。本例中我們使用 Struts 取代了實(shí)例 Web 應(yīng)用程序所發(fā)布的第一個(gè)標(biāo)題頁(yè),您可以試著改變其他的頁(yè)面。下面列出了操作的步驟。

    1. 把 Velocity 庫(kù)復(fù)制到 Struts 示例應(yīng)用程序下的 WEB-INF\lib 目錄中。要使用 Tomcat 5(5.0.16 是撰寫(xiě)本文時(shí)的最新版本)和 Struts 1.1,需要把以下 JAR 文件復(fù)制到 webapps\struts-example\WEB-INF\lib 目錄中:
      • velocity-tools-1.1-beta1.jar
      • velocity-1.4-rc1.jar

    2. 然后在 Struts 配置文件( WEB-INF\struts-config.xml ),把 Struts 動(dòng)作映射設(shè)置為轉(zhuǎn)向 index.vm 文件而不是 index.jsp 文件,如清單 22 所示:
      清單 22. 把 Struts 動(dòng)作轉(zhuǎn)向 index.vm
          <action    path="/logoff"
                     type="org.apache.struts.webapp.example.LogoffAction">
            <forward name="success"              path="/index.vm"/>
          </action>
      


    3. 在部署描述符 WEB-INF\web.xml 文件中配置 VelocityViewServlet 處理 .vm 文件。同樣把歡迎文件設(shè)為 index.vm 而非 index.jsp,如清單 23 所示:
      清單 23. 改變 struts 示例 Web 應(yīng)用程序的部署描述符
      <!-- Action Servlet Configuration -->
        <servlet>
          <servlet-name>action</servlet-name>
          <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
          <init-param>
            <param-name>config</param-name>
            <param-value>/WEB-INF/struts-config.xml, 
            /WEB-INF/struts-config-registration.xml</param-value>
          </init-param>
          <load-on-startup>1</load-on-startup>
        </servlet>
      
      
      
       <servlet>
          <servlet-name>velocity</servlet-name>
          <servlet-class>org.apache.velocity.tools.view.servlet.VelocityViewServlet
          </servlet-class>
          <init-param>
            <param-name>org.apache.velocity.toolbox</param-name>
            <param-value>/WEB-INF/toolbox.xml</param-value>
         </init-param>
          <init-param>
            <param-name>org.apache.velocity.properties</param-name>
            <param-value>/WEB-INF/velocity.properties</param-value>
         </init-param>
        </servlet>
      
      
        <!-- Action Servlet Mapping -->
        <servlet-mapping>
          <servlet-name>action</servlet-name>
          <url-pattern>*.do</url-pattern>
        </servlet-mapping>
      
        <servlet-mapping>
          <servlet-name>velocity</servlet-name>
          <url-pattern>*.vm</url-pattern>
        </servlet-mapping>
      
      
        <!-- The Welcome File List -->
        <welcome-file-list>
          <welcome-file>index.vm</welcome-file>
        </welcome-file-list>
      


    4. 最后,把 toolbox.xml 和 velocity.properties 文件從本文的源代碼下載中(請(qǐng)參閱 參考資料)移動(dòng)到 WEB-INF 目錄下。

    新的 index.vm 文件如清單 24 所示,可以把它與原來(lái)的 index.jsp 文件比較。


    清單 24. 通過(guò)使用 index.vm Velocity 模板與 Struts 互操作
    												
    														<html>
    <head>
    <title>$msg.get("index.title")</title>
    </head>
    <body bgcolor="white">
    
    #if ( !$application.database)
      <font color="red">
        ERROR:  User database not loaded -- check servlet container logs
        for error messages.
      </font>
      <hr>
    #end
    
    <h3>$msg.get("index.heading")</h3>
    <ul>
    <li>
    <a href="$link.setURI("editRegistration.do").addQueryData("action","Create")">
    $msg.get("index.registration")
    </a>
    </li>
    <li>
    <a href="$link.setURI("logon.jsp")">
    $msg.get("index.logon")
    </a>
    </li>
    </ul>
    
    <p>&nbsp;</p>
    <a href="$link.setURI("tour.do")">
    <font size="-1">$msg.get("index.tour")</font>
    </a>
    <p>&nbsp;</p>
    <img src="$link.setURI("powered-by-logo.gif")" alt="Powered by Velocity"/>
    </body>
    </html>
    
    												
    										

    在 index.vm 中,整個(gè)模板都使用 $msg 內(nèi)的消息工具訪問(wèn) Struts 的地域有關(guān)的國(guó)際化資源。通過(guò)對(duì)包含國(guó)際化字符串的資源包的本地化更改,這種方法避免了模板中的多數(shù)硬編碼字符串。

    您可以使用 VTL 的條件指示符 #if 直接檢查在 servlet 上下文中是否存在數(shù)據(jù)庫(kù)屬性。 $application 引用可用于訪問(wèn) servlet 上下文中的任何屬性( $request$response$session 也可用于訪問(wèn)其他 Servlet API 對(duì)象的屬性)。

    LinkTool setURI() 方法用于生成服務(wù)器端到 Struts 動(dòng)作和“Powered by Velocity”標(biāo)志圖片的 URI 鏈接。注意,這里使用 LinkTooladdQueryData() 方法向結(jié)果 URI 種增加附加的動(dòng)作信息。

    要測(cè)試該 Velocity 頁(yè)面,您可以啟動(dòng) Tomcat 5 并訪問(wèn) http://localhost:8080/struts-example/ URL。注意它的結(jié)果與原來(lái)的 JSP 版本完全一致。





    回頁(yè)首


    結(jié)束語(yǔ)

    Velocity 模板處理程序可以直接集成到 Java 語(yǔ)言應(yīng)用程序中,立即提供報(bào)告生成或者模板處理的功能。

    將模板引擎擴(kuò)展到 Web 應(yīng)用程序,可以使用 VelocityServlet 處理動(dòng)態(tài)生成 HTML 輸出的 Velocity 模板。Velocity 工具項(xiàng)目對(duì)使用 VelocityViewServlet 組件化 Web 層應(yīng)用程序開(kāi)發(fā)提供了更多的支持。 VelocityViewServlet 以模板為基礎(chǔ)為基于 Web 的 UI 構(gòu)造提供了方便的視圖層。

    在使用 MVC 模型框架設(shè)計(jì)復(fù)雜的 Web 應(yīng)用程序時(shí),Velocity 作為一種視圖/模板化技術(shù)——以 VelocityViewServlet 的形式——可以很方便地插入到框架中。對(duì)于流行的 Jakarta Struts MVC 框架,Velocity 可以與基于 JSP 的視圖技術(shù)協(xié)作,也可以和選擇的任何模型技術(shù)進(jìn)行交互。

    posted on 2006-05-06 16:02 迷途書(shū)童 閱讀(983) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): java應(yīng)用

    主站蜘蛛池模板: 日本免费高清视频| 亚洲国产高清精品线久久| 最近中文字幕无吗高清免费视频| 午夜成人无码福利免费视频| 狠狠躁狠狠爱免费视频无码| 免费精品99久久国产综合精品| 亚洲精品视频免费在线观看| 成年女人18级毛片毛片免费观看| 九月婷婷亚洲综合在线| 成年女人色毛片免费看| 免费一级特黄特色大片在线| 亚洲中久无码永久在线观看同| 亚洲一区中文字幕久久| 亚洲成av人片天堂网无码】| 国产免费牲交视频免费播放| 131美女爱做免费毛片| 日韩一级免费视频| 亚洲精品无码久久久久sm| 亚洲一区二区三区免费在线观看| 国产午夜亚洲精品不卡| 久久国产乱子伦精品免费不卡 | 国产精品成人免费福利| 国产猛烈高潮尖叫视频免费| 亚洲AV中文无码乱人伦下载| 亚洲日本一线产区和二线| 久久久久久噜噜精品免费直播| 免费观看无遮挡www的小视频| 四虎影库久免费视频| 亚洲欧洲免费视频| 另类专区另类专区亚洲| 一级毛片免费不卡在线| 国产成人免费ā片在线观看| 亚洲成人激情在线| 青青视频免费在线| 无码区日韩特区永久免费系列| 亚洲黄片毛片在线观看| 亚洲xxxxxx| 久草免费福利视频| 免费国产一级特黄久久| 亚洲第一成年人网站| 一道本不卡免费视频|