Velocity空間

          快速構(gòu)建JAVA應(yīng)用
          隨筆 - 11, 文章 - 15, 評論 - 5, 引用 - 0
          數(shù)據(jù)加載中……

          CHAPTER 14 在Turbine里使用Velocity

           

           

          如果你從事Web應(yīng)用程序開發(fā)已經(jīng)很久了,那么你可能已經(jīng)意識到你正花費大量的時間在重新發(fā)明輪子。典型的任務(wù)包括數(shù)據(jù)庫連接池、構(gòu)建控件Servlets、書寫導(dǎo)航菜單和設(shè)計眾多的頁面。重復(fù)使用在哪里?組件?還是框架?幸運的是,許多人已經(jīng)認(rèn)真思考過這個問題,并創(chuàng)建了一些Web開發(fā)者需要的工具。在這一章里,我們將介紹Turbine,它是一個試圖把Web開發(fā)帶入和傳統(tǒng)軟件開發(fā)相同的舞臺的一個框架。為什么這個框架對我們?nèi)绱酥匾吭蚓驮谟谶@個框架依賴Velocity作為MVC模式的view組件。

          Turbine是什么?

          Turbine,Apache軟件開發(fā)組織旗下的Jakarta項目之一,是其眾多使用Velocity進(jìn)行Web開發(fā)的可視化(visible顯著的)中的一個。它包含以下特性:

          它是一個基于Servlets的控制器組件

          它強調(diào)在應(yīng)用程序中(比如購物車)固有的安全

          你可以在不依賴Web的環(huán)境下使用它

          Turbine不僅僅是另一個應(yīng)用程序服務(wù)器,它還是一個應(yīng)用程序框架(application framework),它為開發(fā)者提供了讓他們在構(gòu)建企業(yè)級應(yīng)用程序時所需要的工具,而不需要書寫大量的代碼。這并不是說,你可以把你的應(yīng)用程序直接丟給服務(wù)器。這個框架毫無疑問是一臺主機,同時通過適當(dāng)環(huán)境執(zhí)行,比如TomcatResin。Turbine為你構(gòu)建特定Web應(yīng)用程序提供了一些服務(wù)。另外,Turbine專用于在MVC模式中使用EJB、控制器Servlets和用Velocity寫屏幕的環(huán)境中。

          隨著我們開始尋求理解什么是Turbine和它是怎么和Velocity關(guān)聯(lián)的等問題答案的時候,Turbine變得越來越清晰,Turbine其實就是專門為Web開發(fā)者設(shè)計的。如果你是一個Web設(shè)計者,那么你可能對Java代碼不是太熟悉,可能就需要一段艱苦的時間用于了解Java基礎(chǔ)知識,在這里,哪怕你只具備一點點Java基礎(chǔ)知識,你也可以通過我們提供的詳細(xì)步驟做完全部示例。Velocity的角色就是構(gòu)建在Turbine里需要使用的屏幕輸出。注意,Velocity不是你在Turbine里唯一能夠用的模板語言,Turbine也支持WebMacro、JSPCocoonFreemarker。

          有了這些概念之后,請系好你的安全帶,讓我們開始學(xué)習(xí)使用框架進(jìn)行設(shè)計的激情之旅吧!

          Turbine體系

          首先,你需要一個圍繞Turbine體系進(jìn)行設(shè)計的清晰圖表。Figure 14.1圖解了在這個框架里的不同模塊。


          Figure 14.1
          The Turbine architecture.

          正如你看到的一樣,這個框架包含了5個主要模塊,所有的模塊都在assemblers(匯編程序)的統(tǒng)一指揮下進(jìn)行工作:

          Action完成特定任務(wù)的代碼

          Navigation顯示導(dǎo)航鏈接和控件的Velocity模板

          Screen結(jié)合Velocity模板和Java類,以顯示Layout模塊內(nèi)的關(guān)鍵信息

          Layout描述頁面外觀的Velocity模板

          Page是一個概念上的對象,它包含了所有上面的模塊

          下面我們將按順序解釋每一個模塊

          Action模板

          正如你所期待的一樣,這個Action模塊是用于執(zhí)行一個特定任務(wù)的一小塊Java代碼。其中最重要的任務(wù)就是執(zhí)行將處理信息以HTML<form>方式傳遞給用戶。在Action模塊里的代碼將處理這些信息,并指定給相應(yīng)窗體,但一般而言,你知道,這些信息還需要進(jìn)行驗證、處理,可能的話,還需要進(jìn)行持久化處理。Figure 14.2顯示了在Action和其他模板之間的透視圖。

          Figure 14.2里可以看到,Page模塊執(zhí)行一個Action模塊以響應(yīng)一個POSTGET請求。Action模塊和Page模塊進(jìn)行“溝通(communicates)”,以確定適當(dāng)?shù)钠聊唬?/span>screen)返回給用戶。

          如果你思考一下在此創(chuàng)建的范例,你可以很容易創(chuàng)建一個Action模塊的庫,一個可以在整個Web應(yīng)用程序中重復(fù)使用的庫,而不需要為每一個頁面創(chuàng)建新的代碼。讓我們來考慮一下購物站點的設(shè)計,不管貨品出現(xiàn)在應(yīng)用程序的哪里,用戶都可以隨時把貨品加入到購物車。在Action模塊里為窗體書寫這個處理過程的代碼,你要確保相同的模塊不經(jīng)過任何代碼更改就能夠在整個應(yīng)用程序中使用。


          Figure 14.2
          The Action module flow.

          在傳統(tǒng)的Web開發(fā)模型中,處理窗體的代碼一般在Servlets里,并通過窗體進(jìn)行調(diào)用。然而,在Action模塊里,你可以在這個模塊里保持商業(yè)邏輯和數(shù)據(jù)庫接口,從而把它們從控制器里分離出來。如果你愿意的話,你甚至可以使用EJB

          Navigation模塊

          當(dāng)你訪問一個Web站點的時候,首先呈現(xiàn)給你的是一個頁面導(dǎo)航結(jié)構(gòu)。這個結(jié)構(gòu)可能在頁面的頂部,也可能在頁面底部,或在頁面的左邊。Turbine通過Navigation模塊來支持導(dǎo)航結(jié)構(gòu)。一個Web應(yīng)用程序可以有許多不同的導(dǎo)航結(jié)構(gòu),而且不限位置:可以是頂部、底部、頁面?zhèn)让妗?/span>Navigation模塊被用于處理這個導(dǎo)航結(jié)構(gòu),并這個結(jié)構(gòu)是基于呈現(xiàn)給用戶的頁面細(xì)節(jié)進(jìn)行變化的。通過某些機制來獲取信息,比如EJB,這個模塊就擁有和數(shù)據(jù)庫通信的能力。稍后我們會討論如何通過Layout模塊執(zhí)行Navigation模塊。

          Screen模塊

          一個Web頁面包含了導(dǎo)航信息和頁面有關(guān)的信息。這個重要的頁面內(nèi)容一般放在頁面的body里。在Turbine里通過使用Screen模塊來處理body。這個模塊主要負(fù)責(zé)渲染HTML標(biāo)簽以回傳給用戶。對Screen模塊來說,讓其為用戶的特定信息進(jìn)行數(shù)據(jù)庫訪問并不罕見。

          Layout模塊

          所有的Web頁面在向用戶呈現(xiàn)信息的時候都有一個物理的布局或模板。在某些情況下,相同的模板可以用于整個應(yīng)用程序或站點。在其他情況下,比如書店,例如,模板基于呈現(xiàn)給用戶的頁面進(jìn)行改變。在Turbine里的布局是在Layout模塊里定義的。這個模塊為Navigation模塊、body或在Screen模塊定義的頁面屏幕提供了一個占位符。Layout模塊主要負(fù)責(zé)執(zhí)行ScreenNavigation模塊對頁面布局的依賴。

          Page模塊

          在極大程度上,Page模塊是其他模塊的容器,也是第一個從用戶瀏覽器接受請求的模塊。如果請求包含了一個在Page模塊里定義的actionPage模塊將會被執(zhí)行。在完成action的執(zhí)行后,Page模塊和Screen模塊進(jìn)行通話,以確定將要執(zhí)行的布局。

          模塊對象封裝(Encapsulation

          Figure 14.3里顯示了所有的模塊如何封裝在一起的。如果有用戶瀏覽器請求,將調(diào)用Page模塊,這時,Page模塊執(zhí)行一個裝入的Action模塊。接著,Page模塊繼續(xù)調(diào)用Layout模塊來決定要顯示哪一個屏幕。Layout模塊調(diào)用Navigation模塊來顯示這個頁面的導(dǎo)航信息。最后,Screen模塊被執(zhí)行,用于放置HTML格式的請求信息到頁面上。

          正如你所看見的一樣,Turbine框架把一個Web頁面作為一個對象集來進(jìn)行顯示在頁面里的。每一個對象只負(fù)責(zé)其特定用于頁面的某一部分。


          Figure 14.3
          The Turbine modules.

          Loaders

          相對于我們之前討論的5個模塊來講,Turbine定義了5個類,名叫loaders,每一個加載器負(fù)責(zé)加載其對應(yīng)的特定模塊。Figure 14.4顯示了在Turbine里的loaders層級圖。正如你所看到的一樣,加載器分別用于對應(yīng)5個模塊。


          Figure 14.4
          Loader modules.

          每一個類的成就都融入到Turbine的設(shè)計里,這些加載器賦予他們一定程度的智能。在TurbineResources.properties里,CLASSPATH變量被作為一個屬性進(jìn)行定義,你可以定義一個特定路徑或設(shè)置路徑,用于讓loader嘗試定位資源。一旦loader從硬盤提取資源到內(nèi)存的時候,loader有一個選項用于緩存這些模塊以方便下次再用。正如你所期待的一樣,多個loader可能嘗試加載同一個模塊,因此,所有模塊必須以線程安全方式進(jìn)行書寫。

          Turbine是如何工作的?

          在我們深入討論Turbine和構(gòu)建一些應(yīng)用程序之前。讓我們花一點時間來看一下使用Turbine系統(tǒng)進(jìn)行頁面請求的處理過程。首先,我們大概描述一下test系統(tǒng)的布局。

          用戶通過Web瀏覽器發(fā)出一個請求,這個請求被分派給一個符合Turbine 控制器ServletsURL。由于請求是使用的HTTP方式,因此這就需要在計算機上安裝一個傳統(tǒng)的Web服務(wù)器。這個Web服務(wù)器可以是ApacheResin的內(nèi)建HTTP服務(wù)器。這個Servlets請求被轉(zhuǎn)移到一個在配置文件時指定的應(yīng)用程序服務(wù)器上。

          當(dāng)Turbine Servlets從用戶那里接收到這個請求時,它將對其進(jìn)行檢測看是否是有一個當(dāng)前用戶的HttpSession對象存在。一旦某個Turbine系統(tǒng)的功能是秘密的,那么所有用戶都必須首先登錄到應(yīng)用程序中。這個HttpSession對象將返回登錄的結(jié)果。Turbine在應(yīng)用程序中也使用cookie或帶有session信息的URL。如果沒有HttpSession對象存在,系統(tǒng)將自動切換到登錄頁面,這個切換過程是通過TurbineResources.properties進(jìn)行配置來完成的。

          Turbine Servlets的重要工作之一就是創(chuàng)建運行數(shù)據(jù)(Run-Data)對象。這個對象是非線程安全(non-thread-safe)的對象,用于Action、ScreenDocument對象攜帶信息,所有傳遞給Servlets的信息都是通過Request對象進(jìn)行傳遞的。

          Turbine servlet嘗試通過檢測當(dāng)前為用戶定義的action來決定用戶是否已經(jīng)登錄到應(yīng)用程序中。如果這個action的值為LoginUser,則相應(yīng)的action被執(zhí)行。最后,一個名叫validateUser()的方法調(diào)用被執(zhí)行,在這個方法里,開發(fā)者書寫代碼依靠某些存儲方式(比如數(shù)據(jù)庫)驗證用戶的用戶名和密碼。在確認(rèn)了用戶登錄信息后,用戶將直接返回到登錄屏幕或DefaultPage。所有這些工作都是通過SessionValidator action來完成的,而且它可以進(jìn)行重載以支持更多功能。

          當(dāng)DefaultPage被執(zhí)行時,它將對一個action進(jìn)行檢測并執(zhí)行它。完成這個action后,DefaultPage將詢問Screen模塊以找出DefaultPage的布局,找到后就執(zhí)行它。Layout模塊執(zhí)行NavigationScreen模塊,最后,控件返回給Turbine Servlets和一個新的HTML頁面被轉(zhuǎn)交給用戶。

          獲取和安裝TDK

          使用VelocityTurbine的第一步就是獲取Turbine系統(tǒng)并安裝它。Turbine系統(tǒng)被分成幾個下載。可能在單機模式下使用Turbine,最強大的方式是聯(lián)合使用Turbine、Velocity和一個應(yīng)用程序服務(wù)器(比如Tomcat)。你可以下載以Turbine Development Kit(TDK)方式的需要重配置環(huán)境的Turbine,下載地址是:ttp://jakarta.apache.org/ builds/jakarta-turbine/release/

          在這個地址,你可以找到所有TDKreleased版本。寫本書的時候,最新版為2.1。進(jìn)行最新版的Turbine目錄,你將看到TAR.GZUnix/Linux)和zip文件(Windows)TDK、TurbineTorque。由于我們只想下載TDK,因此,我們只需下載對象工作環(huán)境的TDK即可。

          下載完成后,解壓文件到一個指定目錄。解壓完成后,將生成一個帶有眾多子目錄的/tdk目錄。

          在測試安裝之前,你必須在你的系統(tǒng)上安裝兩個附加系統(tǒng):

          Ant下載URLjakarta.apache.org/ant

          JDK下載URLsun.java.com

          測試TDK安裝

          測試TDK的安裝包括兩個步驟。

          首先你必須配合TDK編譯示例應(yīng)用程序,步驟為:進(jìn)入/tdk目錄,執(zhí)行Ant命令(簡單鍵入ant),Ant應(yīng)用程序?qū)⒒?/span>/tdk目錄的build.xml文件執(zhí)行,過幾秒鐘后,構(gòu)建完成。在很多情況下,構(gòu)建是成功的。如果不成功,請檢查Turbine官方站點的郵件列表。

          構(gòu)建完成后,就可以進(jìn)行系統(tǒng)測試了。進(jìn)入/TDK根目錄下的/bin目錄。TDK的部分部件安裝已經(jīng)完成,只需要重新裝配應(yīng)用程序服務(wù)器Tomcat即可。雖然TurbineVelocity都可以在Resin上使用(稍后討論),但Tomcat是我們推薦的最佳應(yīng)用服務(wù)器。

          windows下用下面的命令啟動Tomcat

          catalina.bat run

          Unix/Linux下用下面的命令啟動Tomcat

          catalina.sh start

          如果啟動成功,你將看到如下的信息

          Using CLASSPATH: .."bin"bootstrap.jar;c:"j2sdk1.4.1_01"lib"tools.jar

          Starting service Tomcat-Standalone

          Apache Tomcat/4.0-b6-dev

          Starting service Tomcat-Apache

          Apache Tomcat/4.0-b6-dev

          Tomcat啟動后,在瀏覽器輸入下面的URL來查看TDK示例:

          http://localhost:8080/newapp/servlet/newapp

          如果運行成功的話,你可以看到Figure 14.5所示的輸出。


          Figure 14.5
          TDK sample application.

          在這里,你可以看到你安裝的TDK已經(jīng)成功。如果你對TDK的應(yīng)用程序示例感興趣,你可以,你可以使用下面的的URL來查閱相關(guān)文檔。

          http://localhost:8080

          你的第一個Turbine應(yīng)用程序

          安裝完TDK后,你就可以開始使用Turbine作為MVC框架、Velocity作為view組件來構(gòu)建你自己的應(yīng)用程序了。第一步是為Ant build文件增加一個任務(wù),并在build.properties里增加一個適當(dāng)?shù)哪夸浗Y(jié)構(gòu)。打開位于/tdk根目錄下的build.properties文件,修改這個文件里的三個變量:

          turbine.app指定應(yīng)用程序(在我們的示例里為testApplication

          target.package指定應(yīng)用程序包(在我們的示例里為:com.company. testApplication

          target.directory指定將要構(gòu)建的包的存放目錄(通常情況下為target.package,在我們的示例里為:com/company/testApplication

          下一步,Ant將構(gòu)建你的新應(yīng)用程序。記住,Turbine只是一個框架,因此你將得到許多自由的服務(wù)。Ant腳本移動不同的文件到你指定的應(yīng)用程序目錄。在下一節(jié)里,我們將對這些放置到這個指定目錄的文件進(jìn)行研究。

          Turbine(和你的應(yīng)用程序)將使用一個數(shù)據(jù)庫。當(dāng)我們構(gòu)建一個新Turbine應(yīng)用程序的時候,需要進(jìn)入/tdk/webapps/<your application name>/WEB-INF/build目錄,并打開build.properties文件,修改以下內(nèi)容:

          定位database(數(shù)據(jù)庫)輸入,將其默認(rèn)為mysql,并設(shè)置好相應(yīng)的值。這個值會在Turbine創(chuàng)建SQL語句的時候使用。

          定位databaseUrll輸入,并增加適當(dāng)?shù)?/span>JDBC連接字符串,同時把JDBC驅(qū)動放到/WEB-INF/lib目錄。

          修改databaseDriver輸入為JDBC驅(qū)動類。

          修改databaseUser為數(shù)據(jù)庫登錄用戶

          修改databasePassword為數(shù)據(jù)登錄用戶密碼

          修改databaseHost為服務(wù)器的IP地址

          在這里,系統(tǒng)必須為Turbine創(chuàng)建一個數(shù)據(jù)庫表。因此,進(jìn)入/tdk/webapps/<your application name>/WEB-INF/build目錄,并執(zhí)行ant init。這個Ant構(gòu)建腳本將用你在build.properties屬性里指定的內(nèi)容連接到數(shù)據(jù)庫,并創(chuàng)建所需的表。當(dāng)任意一個初始化命名被執(zhí)行的時候,可能會發(fā)生許多錯誤。比如,build.xml文件只尋找Windows 98、Windows NTWindows 2000,但如果你用的是Windows XP的話,只需把所有的“98”修改成“XP”或為XP增加一個<target>元素。另外一個是在構(gòu)建腳本嘗試訪問數(shù)據(jù)庫命令行管理工具時可能會出現(xiàn)錯誤。請確保你的數(shù)據(jù)庫服務(wù)器下的/bin目錄被包含進(jìn)操作系統(tǒng)路徑(path)。

          一旦Ant初始化命令成功執(zhí)行,就可以嘗試編輯你的新應(yīng)用程序了(記住,我們將使用Velocity來進(jìn)行頁面表現(xiàn))。為了查看你的應(yīng)用程序,請啟動Tomcat,之后瀏覽下面的URL

          http://localhost:8080/testApplication/servlet/testApplication

          你將看到一個Turbine登錄頁面,見Figure 14.6

          為了訪問你的新應(yīng)用程序,請鍵入turbine作為你的用戶名和密碼。登錄后的頁面見Figure 14.7

          現(xiàn)在讓我們回頭看看你剛才構(gòu)建的應(yīng)用程序,看如何對其進(jìn)行擴展來完成一些你想做的事情。


          Figure 14.6
          The Turbine login.


          Figure 14.7
          The Turbine main page.

          解剖(Dissecting)這個應(yīng)用程序

          Okay,你已經(jīng)安裝完成Turbine,并看到了示例的輸出。但它到底做了些什么?好,讓我們來看一下這個應(yīng)用程序,并看一下如何把我們所學(xué)的Velocity應(yīng)用到進(jìn)而去。讓我們從頭到尾看一下這個應(yīng)用程序,并討論幾個基礎(chǔ)類、方法和Turbine應(yīng)用程序的功能調(diào)用。

          當(dāng)你在之前瀏覽這個應(yīng)用程序示例的時候,控件被傳遞給Turbine Servlets調(diào)用的普通Servlets。不管在這個Servlets里到底發(fā)生了什么,你需要幾個類型的HTML輸出來提供給客戶端。下面你將會看到,這里僅有兩條路可以接觸服務(wù)器,既通過鏈接或窗體。在第一情況下,你通過主應(yīng)用程序URL來調(diào)用服務(wù)器。

          這個應(yīng)用程序的URL首先被Web服務(wù)器處理,這個Web服務(wù)器可是內(nèi)嵌型服務(wù)器,也可以是獨立的Web服務(wù)器。當(dāng)URL最后傳遞到應(yīng)用程序服務(wù)器的時候,它將檢查它的主機列表,之后決定這個URL是否和他們匹配。在這種情況下,Tomcat找到這個應(yīng)用程序testApplication就是主機并存在對應(yīng)的目錄結(jié)構(gòu)。其中第一件TomcatResin需要做的事就是打開web.xml文件,并定位應(yīng)用程序的/WEB-INF目錄。這是一個配置文件,用于告訴服務(wù)器當(dāng)一個詳細(xì)的URL被發(fā)現(xiàn)的時候需要執(zhí)行哪一個類。你的應(yīng)用程序的web.xml文件包含這些元素:

          <servlet-name>testApplication</servlet-name>

          <servlet-class>org.apache.turbine.Turbine</servlet-class>

          這些元素告訴應(yīng)用程序服務(wù)器去執(zhí)行在Turbine類里找到的代碼。當(dāng)Turbine ServletsTurbine類里被發(fā)現(xiàn)的時候正是如此。當(dāng)Turbine Servlets執(zhí)行的時候,它立即嘗試執(zhí)行一個默認(rèn)頁面。這個應(yīng)用程序的默認(rèn)頁面在/WEBINF/conf/TurbineResource.properties文件里進(jìn)行定義。大約25%的情況下會設(shè)成

          services.VelocityService/default.layout.template = /Default.vm

          因此,因為在你的應(yīng)用程序里沒有布局或action(后面會介紹如何增加),因此Turbine Servlets使用了default.vm布局。這個default.vm布局(Listing 14.1)位于/templates/app/layouts目錄。

          <table width="100%">

          <tr>

          <td colspan="2">

          $navigation.setTemplate("/DefaultTop.vm")

          </td>

          </tr>

          <tr>

          <td width="20" align="left" valign="top">

          $navigation.setTemplate("/Menu.vm")

          </td>

          <td align="left" valign="top">

          $screen_placeholder

          </td>

          </tr>

          <tr>

          <td colspan="2">

          $navigation.setTemplate("/DefaultBottom.vm")

          </td>

          </tr>

          </table>

          Listing 14.1 The default.vm Velocity template.

          在你的應(yīng)用程序晨,default.vm文件是一個Layout模塊頁面。在這個文件里的代碼用于呈現(xiàn)將要返回給用戶瀏覽器的頁面內(nèi)容。在這個頁面上沒有太多內(nèi)容,你可以很容易的增加不同的可視化(look-and-feel)組件,比如一個顏色背景和插圖(和12章的CD應(yīng)用程序一樣)。這個default.vm文件包含了4Velocity引用:

          第一個是位于頁面頂部的導(dǎo)航組件

          第二個也是導(dǎo)航組件,呈現(xiàn)為一個在頁面左側(cè)的導(dǎo)航條

          第三個是一個屏幕組件,用作頁面的身體body

          第四個是位于屏幕底部的另一個導(dǎo)航組件

          任何在這個模板里的改變將反映到輸出到用戶的頁面上。

          在這里,你或許會問,$navigation.setTemplate(String)方法到底做了些什么?還記得Velocity允許得到依靠上下文里的對象的方法調(diào)用嗎?$navigation.setTemplate(String)得到一個方法調(diào)用,setTemplate(String)依靠的是在上下文里的$navigation對象。方法的調(diào)用結(jié)果將被放入模板default.vm中,并返回給用戶?,F(xiàn)在,在default.vm模板中的改動將被放入內(nèi)存中,因此,它不是持久性的。在這種$screen_placeholder引用情況下,Velocity解析將嘗試用$screen_placeholder引用來進(jìn)行替換這個引用。我們知道,在Turbine的處理流程中,Layout模塊調(diào)用適當(dāng)?shù)?/span>Screen模塊,并自動從Screen模塊返回的代碼替換進(jìn)$screen_placeholder里。所有這些處理過程不需要任何人為干預(yù)。其中的一些過程的理解或許有困難,因此一定堅持住,繼續(xù)探索究竟發(fā)生了什么。

          你或許會問$navigation$screen_placeholder是在哪里被替換的?這兩個引用使用的對象放置在Turbine Servlets支持的上下文中。實際上,有些替換過程是自動完成的,我們讓Turbine處理這些引用。因此,Turbine得到Layout文件并嘗試去決定每一個引用。讓我們看一下導(dǎo)航組件中一個模板文件,是menu.vm模板文件的代碼,見Listing 14.2。

          <font face="$ui.sansSerifFonts">

          <a href="$link.setPage("Insert.vm")">Insert Entry</a>

          <p>

          <b>Flux</b>

          <br>

          <a href="$link.setPage("user,FluxUserList.vm")">Users</a>

          <br>

          <a href="$link.setPage("group,FluxGroupList.vm")">Groups</a>

          <br>

          <a href="$link.setPage("role,FluxRoleList.vm")">Roles</a>

          <br>

          <a href="$link.setPage("permission,FluxPermissionList.

          vm")">Permissions</a>

          <p>

          <b>Services</b>

          ##<br>

          ##<a href="">Intake Service</a>

          ##<br>

          ##<a href="">Localization Service</a>

          ##<br>

          ##<a href="">Pull Service</a>

          ##<br>

          ##<a href="">Scheduler Service</a>

          <br>

          <a href="$link.setPage("Upload.vm")">Upload Service</a>

          <br>

          <a href="$link.setPage("ServletInfo.vm")">Servlet Service</a>

          <br>

          ##<a href="">Unique Id Service</a>

          ##<br>

          ##<a href="">XML-RPC Service</a>

          ##<br>

          ##<a href="">XSLT Service</a>

          <p>

          <b>Common Tasks</b>

          <br>

          <a href="">User Downloads</a>

          <p>

          <a href="$link.setPage("Index.vm")">Home</a>

          <p>

          <a href="$link.setAction("LogoutUser")">Logout</a>

          Listing 14.2 The menu.vm Velocity template. (continued)

          這個menu.vm模板包含相當(dāng)多的Velocity代碼。兩個不同的調(diào)用了上下文。第一個是$link.setPage(String)方法調(diào)用。這個代碼訪問了上下文中的“link”對象,并向其傳遞Velocity模板的名稱,用于當(dāng)用戶單擊鏈接的時候。當(dāng)用戶不允許cookie時,系統(tǒng)將為這個用戶增加適當(dāng)?shù)穆窂叫畔⒉⑶矣锌赡苄薷倪@個URL以滿足這種情況下的訪問。$link.setPage(“Upload.vm”)調(diào)用產(chǎn)生一個如下所示的鏈接:

          http://localhost:8080/TestApplication/servlet/TestApplication/template/Upload.vm

          接下來是setAction(String),另一個用于上下文中鏈接對象的方法調(diào)用。這個方法也用于頁面的鏈接,但它不僅僅是放入一個鏈接,你將獲得一個聯(lián)合了action的鏈接。這個$link.setAction(“LogoutUser”)將產(chǎn)生下面的鏈接

          http://localhost:8080/TestApplication/servlet/TestApplication/action/LogoutUser

          正如你所期待的一樣,在一些窗體里,用戶退出登錄action是一個Java類,它是一個擴展自Action基類。正如你看到的一樣,通過這個示例應(yīng)用程序的代碼,你可以看到下面的代碼

          $link.setPage(“UploadComplete.vm”).setAction(“Upload”)

          這種類型的調(diào)用會為一個模板創(chuàng)建了一個鏈接,并且指示一個必須執(zhí)行的action。正如我們之前討論的一樣,這個action將在頁面被構(gòu)建之前執(zhí)行。

          現(xiàn)在你或許會驚訝填充$screen_placeholder的代碼來自哪里?這里有一小點竅門,$screen_placeholder的信息是通過Screen模塊產(chǎn)生的。Screen模塊是使用兩個組件來創(chuàng)建的:一個Velocity模板和一個Java類。這個模板提供了一個可視化界面(look and feel),Java類為這個模板增加引用到上下文給用戶。在本章的后面,我們將解釋為什么這兩個組件都是必需的。為了讓系統(tǒng)能夠正常工作,模板得到一個和Java類一模一樣的名稱。

          那么,當(dāng)default.vm布局被使用的時候,既然Screen模塊并沒有在URL中指定,那么它是從哪里獲得的呢?答案是:TurbineResources.properties文件在后臺支持的。在這個文件里有兩個實體:

          template.homepage=/Index.vm

          template.login=/Login.vm

          因為沒有在URL中指定屏幕,Turbine將自動使用index.vm屏幕。這個屏幕的代碼在webapps/TestApplication/templates/app/screens目錄下,具體內(nèi)容見Listing 14.3。你的系統(tǒng)依靠你想顯示的屏幕,使用Velocity模板來替換占位符。

          $page.setTitle("Index")

          $page.setBgColor("#ffffff")

          #set ( $headings = ["Title", "Dept", "Author", "Url","Body"," "] )

          #if ($entries)

          <table>

          <tr>

          <td>

          <table cellspacing="1" cellpadding="1">

          <tr>

          #foreach ($heading in $headings)

          #headerCell ($heading)

          #end

          </tr>

          #foreach ($entry in $entries)

          <tr>

          #entryCell ($entry.Title)

          #entryCell ($entry.Dept)

          #entryCell ($entry.Author)

          #entryCell ($entry.Url)

          #entryCell ($entry.Body)

          <td><a href="$link.setPage("Form.vm").addPathInfo("rdfid",

          $entry.RdfId)">Edit</a></td>

          </tr>

          #end

          </table>

          </td>

          </tr>

          </table>

          #end

          Listing 14.3 The index.vm code. (continud)

          Listing 14.3里的代碼是許多屏幕中的一個屏幕的代碼,讓你可以用作在default.vm頁面里的$screen_placeholder的代替者。我們想指出在這個列表里的幾件事。第一,注意這個頁面是用于顯示產(chǎn)生于數(shù)據(jù)庫的動態(tài)數(shù)據(jù)的,通過$entries reference。$entries reference被填充并且被加入到index.java頁面的上下文中,見Listing 14.4。因為這個Java類的名稱和模板的名稱相同,因此,當(dāng)index.java類被用戶瀏覽器調(diào)用時,Turbine系統(tǒng)會自動使用index.vm。這就是index.java類的責(zé)任,既把適當(dāng)?shù)闹捣湃?/span>$entries reference。第二,注意index.vm這個Velocity模板,它使用了Velocimacros#entryCell()是一個宏,它提供顯示表的格式。

          package org.mycompany.newapp.modules.screens;

          import java.util.Vector;

          import org.apache.turbine.modules.screens.VelocityScreen;

          import org.apache.turbine.util.RunData;

          import org.apache.turbine.util.db.Criteria;

          import org.mycompany.newapp.om.RdfPeer;

          import org.apache.velocity.context.Context;

          public class Index extends SecureScreen {

          public void doBuildTemplate(RunData data, Context context) {

          context.put("entries", getEntries());

          }

          private Vector getEntries() {

          try {

          Criteria criteria = new Criteria();

          return RdfPeer.doSelect(criteria);

          } catch (Exception e) {

          return null;

          }

          }

          }

          Listing 14.4 Java code for the index.vm template.

          正如你所看見的,index.java繼承自SecureScreen類,意思是這個Index類是一個屏幕,并且它需要用戶先登錄系統(tǒng)后才能顯示。OK,讓我們在這兒停一下。這個SecureScreen類源自一個名叫VelocityScreenTurbine基類。所有Screen模塊都繼承自VelocityScreen(如果需要驗證的話)。然而,所有的這些都依賴于我們之前列出來的template.login屬性。如果這兒有一個適當(dāng)?shù)哪0?,并且為登錄屬性?lián)合了Java類,那么用戶必須先登錄后才能使用這個模板。如果你從template.login屬性中移去/login.vm,系統(tǒng)將不會提示你需要登錄,因為它不知道把哪一個默認(rèn)屏幕發(fā)給用戶,讓他登錄到系統(tǒng)來。

          讓我們回到index.java文件。Index類的目的是創(chuàng)建一個$entries引用,以便讓index.vm模板可以獲得數(shù)據(jù)并返回給用戶。在VelocityScreen基類里,SecureScreen類起源于一個名叫doBuildTemplate()的方法。當(dāng)一個Screen模塊需要返回它的模板的時候,這個方法會被Turbine系統(tǒng)自動調(diào)用。因此,Turbine調(diào)用doBuildTemplate()方法,Screen模塊將把所有必須的Velocity引用放入到上下文中,并且所有關(guān)聯(lián)的模板將獲得Turbine放置在$screen_placeholder引用里的引用,用于最后返回HTML,所有這些都很非常好、非常整潔。

          在你運行代碼之前,先來看一看所有的平面輸出。讓我們花一點時間來解釋doBuildTemplate()方法和一些在Velocity模板index.vm上的引用。雖然你不能看見他們,index.vmindex.java文件查詢數(shù)據(jù)庫并顯示任何一個結(jié)果。你需要理解這個,以便你可以在你自己的代碼里使用相同的技術(shù)。

          從高層次(high level)來說,在index.java文件里的代碼把一個名叫$entries引用放入到上下文中,并且通過getEntries()方法返回這個引用和它的值。getEntries()方法使用了一個Peer對象,這是一個助手對象,用于履行一個在數(shù)據(jù)庫上的選擇。數(shù)據(jù)庫結(jié)果行被放入上下文中。

          OK,所有的用意是什么?當(dāng)Layout模塊調(diào)用index Screen模塊時,doBuildTemplate()方法被執(zhí)行,它把一個名叫$entries的引用加入所提供的上下文對象中。通過Index類里的getEntries()方法,$entries和它的值一起被獲取。雖然這個方法只包含了兩行代碼,但有許多工作是在里面完成的。

          第一行代碼包含了一個Criteria類型的對象,Criteria類是一個助手類,用于從Turbine和一個名叫Torque的關(guān)聯(lián)包管理的數(shù)據(jù)庫獲取信息。使用Criteria類,你可以放置過濾器(filter)或限制一個SELECT SQL命令執(zhí)行。當(dāng)沒有參數(shù)的實例或額外的方法在使用它的時候,對象將通知,一個SELECT將把所有的行和列從數(shù)據(jù)庫里取出。Criteria對象的方法完整列表見現(xiàn)在這個URLhttp://jakarta.apache.org/turbine/torque-3.0.0/apidocs/org/apache/torque/util/Criteria.html

          getEntries()里的最后一行代碼返回

          RdfPeer.doSelect(criteria);

          許多事情都發(fā)生在這個語句上,并且我們需要得到一個數(shù)據(jù)庫以避開對其進(jìn)行說明。

          Turbine里操作數(shù)據(jù)庫

          所有在Turbine應(yīng)用程序里的數(shù)據(jù)庫都是在配置文件里定義的,這個配置文件為/webapps/testApplication/WEB-INF/conf/testapplication-schema.xml,Listing 14.5顯示這個文件里的代碼

          <database>

          <table name="RDF">

          <column name="RDF_ID" required="true" autoIncrement="true"

          primaryKey="true" type="INTEGER"/>

          <column name="TITLE" size="255" type="VARCHAR"/>

          <column name="BODY" size="255" type="VARCHAR"/>

          <column name="URL" size="255" type="VARCHAR"/>

          <column name="AUTHOR" size="255" type="VARCHAR"/>

          <column name="DEPT" size="255" type="VARCHAR"/>

          </table>

          </database>

          Listing 14.5 The database schema XML.

          從這個列表里,你可以看到在Turbine里定義一個數(shù)據(jù)庫非常容易。只需要為一個特定的列(particular column)提供列、大小、類型和其他屬性。你可以通過以下命令增加一個表到你的數(shù)據(jù)庫

          ant init

          /webapps/testApplication/WEB-INF/build目錄,當(dāng)你做的時候,Ant執(zhí)行了數(shù)據(jù)庫的所有在XML文件里定義好的構(gòu)建任務(wù)。如果你關(guān)注一下Ant構(gòu)建XML文件的執(zhí)行情況,你可以看到第一個操作是使用在XML文件里定義的表名稱DROP任意表。因此,所有已經(jīng)存在的表的數(shù)據(jù)將全部丟失。你可以修改Ant任務(wù)或在執(zhí)行任務(wù)之前先確認(rèn)你的所有表定義。

          Figure 14.8 shows a listing of the tables produced for the testApplication.


          Figure 14.8
          Tables for testApplication in MySQL.

          當(dāng)一個新表被創(chuàng)建的時候,會發(fā)生兩個主要的操作。第一個是,在數(shù)據(jù)庫配置里定義的結(jié)構(gòu)被寫入數(shù)據(jù)庫(Turbine配置的一部分)。第二個是執(zhí)行處理SELECTINSERTDELETEUPDATE的代碼,以及其他的數(shù)據(jù)庫操作任務(wù)。所有這些代碼被放在/webapps/testApplication/WEB-INF/src/java/com/company/testApplication/om目錄下。這個路徑com/company/testApplication依賴于你的應(yīng)用程序名稱。

          在這個目錄里,你可以找到四個文件,他們包含你的表的名稱。在RDF表的創(chuàng)建是通過Turbine使用Torque系統(tǒng)完成的,這些文件是:

          BaseRdf.java

          BaseRdfPeer.java

          Rdf.java

          PdfPeer.java

          BaseRdf.java文件為數(shù)據(jù)庫行包含了所有的setter/getter方法。請不要修改這個文件。Rdf.java文件是一個從BaseRdf.java衍生而來的類,如果需要的話,可用于定義應(yīng)用程序邏輯。BaseRdf-Peer.java文件是一個助手類,它使用BaseRdf.java文件來進(jìn)行低級數(shù)據(jù)庫操作,其對象包含的方法可以完成所有普通的數(shù)據(jù)庫操作。RdfPeer.java文件是一個從BaseRdfPeer.java衍生而來的類,在這里可以放置應(yīng)用程序邏輯,其用于代碼的對象將用于獲取或放置適當(dāng)?shù)谋怼?/span>

          執(zhí)行Select

          基于我們已經(jīng)呈現(xiàn)的信息,getEntries()方法創(chuàng)建了一個Criteria對象,沒有任何表限制或結(jié)果返回。接著,Criteria對象被提供給RdfPeer類的doSelect()方法。這個方法在RdfPeer類里沒有重載,因此,一個調(diào)用創(chuàng)建了BaseRdfPeer類的doSelect()方法。這個方法基于傳遞進(jìn)來的Criteria對象從數(shù)據(jù)庫里重新得到行。

          顯示結(jié)果

          一旦getEntries()返回,從RDF表返回的行被作為$entries引用的值放到上下文對象中。在Index對象完成它的工作之后,Turbine Servlets將合并上下文和index.vm模板,以為$screen_placeholder引用提供代碼。最后一步是返回一個HTML頁面給用戶。

          使用testApplicationAdding增加一個用戶

          在從default.vm布局返回給用戶的頁面和index.vm/java Screen模塊的左邊導(dǎo)航條上都有許多的鏈接。第一個鏈接叫“Insert Entry”,其href屬性指定的是一個Velocity代碼。

          <a href=”$link.setPage(“Insert.vm”)”>Insert Entry</a>

          其對應(yīng)的URL

          http://localhost:8080/testApplication/servlet/testApplication/template/Insert.vm

          正如你看到的一樣,這個和我們最原始的URL比較想似,除了我們現(xiàn)在有一個新路徑信息/template/Insert.vm外。當(dāng)你單擊這個鏈接時,default.vm布局被使用,而不是默認(rèn)的index.vm,你已經(jīng)告訴Turbine Servlets,讓他使用由insert.vminsert.java聯(lián)合定義的Screen模塊?,F(xiàn)在讓我們來看一下Listing 14.6里的insert.vm。

          $page.setTitle("Insert")

          <meta http-equiv="Content-Type" content="text/html; charset=iso-

          8859-1">

          </head>

          <body bgcolor="#ffffff" leftmargin="0" topmargin="0"

          marginwidth="0" marginheight="0">

          <form

          method="post"

          action="$link.setPage("Index.vm").setAction("SQL")">

          <div align="left">

          <table bgcolor="#ffffff" cellpadding="5">

          <tr>

          #formCell ("Title" "title" "")

          </tr>

          <tr>

          #formCell ("Author" "author" "")

          </tr>

          <tr>

          #formCell ("Department" "dept" "")

          </tr>

          <tr>

          #formCell ("Url" "url" "")

          </tr>

          <tr>

          #formCell ("Body" "body" "")

          </tr>

          </table>

          <input type="submit" name="eventSubmit_doInsert" value="Insert"/>

          </div>

          </form>

          Listing 14.6 The insert.vm Velocity template.

          我們已經(jīng)介紹了Velocity模板insert.vm里面幾乎所有的東西。然而,這個時候,包含在<form>標(biāo)簽里的代碼。這個標(biāo)簽用于從用戶和支持它的服務(wù)器中提取數(shù)據(jù)庫的數(shù)據(jù)。這個窗體action包含了一個Turbine action模塊引用:

          <form action=”$link.setPage(“Index.vm”).setAction(“SQL”)”>

          Turbine action被找到并作為一個SQL action調(diào)用。用于告訴SQL action如何去做,這個輸入按鈕有一個名稱叫eventSubmit_doInsert,讓我們思考一下代碼是如何做的。首先,用戶單擊Insert Entry鏈接,Turbine servlet提出默認(rèn)的布局default.vm用于渲染適當(dāng)?shù)?/span>Navigation模塊,除了調(diào)用insert.java類的doBuildTemplate()方法外。然而,如果你看一下/src/com/mycompany/testApplication/modules/screens/目錄,你就會發(fā)現(xiàn)insert.java的源文件。這就提出了一個好的點子,Screen模塊不再需要由VMJava類文件組成。如果一個Screen模塊只有一個VM模板,Turbine服務(wù)器只需簡單渲染Velocity模板而不需要任何上下文的改變。如果僅包含了一個Screen類,這個類將負(fù)責(zé)提供所有的輸出支持,因為這個沒有Velocity模板來渲染HTML輸出。

          在這里,Velocity模板insert.vm基于當(dāng)前上下文對象被渲染為$screen_placeholder引用。在這點上,用戶在<form>輸出字段輸入數(shù)據(jù)并單擊提交按鈕。這個單擊將導(dǎo)致Turbine servlet執(zhí)行一個Action模塊來調(diào)用SQL。記住在Layout對象之前,所有的action都將被執(zhí)行。

          SQL actionmodules/actions目錄下。這個action的源文件在/src/com/mycompany/testApplication/modules/actions目錄下的SQL.java文件(Listing 14.7)。

          import org.apache.velocity.context.Context;

          import org.apache.turbine.util.RunData;

          import org.apache.turbine.util.db.Criteria;

          import org.apache.turbine.modules.actions.VelocityAction;

          import com.company.testApplication.om.Rdf;

          import com.company.testApplication.om.RdfPeer;

          public class SQL extends SecureAction {

          public void doInsert(RunData data, Context context)

          throws Exception {

          Rdf entry = new Rdf();

          data.getParameters().setProperties(entry);

          entry.save();

          }

          public void doUpdate(RunData data, Context context)

          throws Exception {

          Rdf entry = new Rdf();

          data.getParameters().setProperties(entry);

          entry.setModified(true);

          entry.setNew(false);

          entry.save();

          }

          public void doDelete(RunData data, Context context)

          throws Exception {

          Criteria criteria = new Criteria();

          criteria.add(RdfPeer.RDF_ID, data.getParameters().getInt("rdfid"));

          RdfPeer.doDelete(criteria);

          }

          public void doPerform(RunData data, Context context)

          throws Exception {

          data.setMessage("Can't find the button!");

          }

          }

          Listing 14.7 The SQL Action class.

          SQL Action用于SecureAction。通過使用SecureAction基類,只有當(dāng)用戶登錄進(jìn)系統(tǒng)后,這個action才會被執(zhí)行。提交按鈕使用了一個doInsert的值,在doInsert()方法里,系統(tǒng)利用全局runData對象,在這里,來自<form>的參數(shù)被定位。在這種情況下,你不能為RDF表使用Peer對象,但可以使用RDF類自身。這個來自<form>的值被替換成RDF對象并存入數(shù)據(jù)庫。

          一旦SQL Action把新信息存儲到適當(dāng)?shù)臄?shù)據(jù)庫,使用它的Navigation模塊來執(zhí)行默認(rèn)的布局,同時index.vm屏幕在<form action>里指定。Figure 14.9顯示了我們向數(shù)據(jù)庫增加一個新實體后的情況,Figure 14.10顯示了testApplication頁面。


          Figure 14.9 A database entry in MySQL.


          Figure 14.10
          The testApplication page after the insert.

          注意在Figure 14.10屏幕右上邊的“edit”鏈接。如果你把鼠標(biāo)移至鏈接的上方,你可以看到現(xiàn)在的鏈接

          http://localhost:8080/testApplication/servet/testApplication/tempalte/Form.vm/rdfid/1

          在這里,你應(yīng)該知道當(dāng)你單擊這個鏈接的時候,這些代碼打算做些什么。form.vmform.java Screen模塊文件被調(diào)用。這個時候,你需要有一個form.java文件。正如你料想的一樣,在URL末尾的rdfid/1信息將用于從數(shù)據(jù)庫提取行并顯示它,見Figure 14.11。Form類的代碼見Listing 14.8。


          Figure 14.11
          An edit on the database row.

          public class Form extends SecureScreen {

          public void doBuildTemplate( RunData data, Context context {

          try {

          int entry_id = data.getParameters().getInt("rdfid");

          Criteria criteria = new Criteria();

          criteria.add(RdfPeer.RDF_ID, entry_id);

          Rdf rdf = (Rdf) RdfPeer.doSelect(criteria).elementAt(0);

          context.put("entry", rdf);

          } catch (Exception e){

          }

          }

          }

          Listing 14.8 The form.java code.

          正如你所知道的一樣,Screen模塊代碼在Velocity模板之前執(zhí)行。因此在Listing 14.8里的doBuildTemplate()代碼通過鏈接獲得主要關(guān)鍵字,并用于提取數(shù)據(jù)庫行、替換上下文中的Velocity模板form.vm來顯示給用戶。在鏈接末尾的rdfid被轉(zhuǎn)換成一個參數(shù),并且被放到RunData對象中。之后,它使用Criteria對象來定位數(shù)據(jù)庫,并從數(shù)據(jù)庫提取數(shù)據(jù)行。elementAt(0)方法被用于把一個數(shù)據(jù)行中放入上下文的“entry”引用中。

          注意那些action是不返回結(jié)果的。當(dāng)你需要從數(shù)據(jù)庫中得到信息的時候,只需為Screen模塊使用一個類就行。如果這兒有你需要的action來傳達(dá),你可以通過使用data.setMessage(String)命令在RunData對象中設(shè)置一個消息變量。

          當(dāng)書寫你的action的時候,你需要從VelocityActionSecure Action類(依賴于是否需要進(jìn)行登錄驗證)開始。在任意一種情況下,這個action都包含了一個或多個ActionEvent。正如你在SQL Action里看到的,那里的事件都用于提交按鈕的值和一名名叫doPerform(RunData, Context)的方法。doPerform()方法是一個action的默認(rèn)方法。如果沒有其他的方法可用或在單擊窗體上的按鈕沒有匹配的ActionEvents(在類里)時,doPerform()方法將會被執(zhí)行。

          重建和部署

          一旦你修改了你的應(yīng)用程序,你就必須重建它。在當(dāng)前的TDK環(huán)境下非常容易,只需進(jìn)入/webapps/testApplication/WEB-INF/build目錄,并執(zhí)行下面的命令

          ant compile

          最后,當(dāng)TurbineTomcat上運行時,就不再需要它了。如果你想轉(zhuǎn)移到Resin平臺或BOSS或其他應(yīng)用程序服務(wù)器,只需要打包你的testApplication或其他應(yīng)用程序名稱目錄結(jié)構(gòu)并在別處進(jìn)行部署就行。你或許會需要刪除或調(diào)整在web.xml文件中DTD。

          Turbine里使用Velocity的高級功能

          最后一節(jié)比較簡略,我們將介紹在Turbine里使用Velocity的許多主要特性。然而,我們想介紹一點附加的高級特性。當(dāng)然,你可以查閱Turbine文檔以獲得更多信息。

          RunData對象

          在整個示例應(yīng)用程序中,我們談到了RunData對象,并且通過使用數(shù)據(jù)關(guān)鍵字獲取了一個該對象的引用。RunData對象有許多方法和許多有益于開發(fā)的字段。既然RunData對象在模板和許多模塊Java類中可以使用,那么開發(fā)者就應(yīng)該充分利用這個對象。該對象的一些方法為:

          void setMessage(String msg)RunData對象里設(shè)置一條消息,這個常用于錯誤處理和其他模塊間的信息傳遞,比如Action模塊

          string getMessage()返回一條RunData信息

          parameter Parser getParameters()返回從一個HTML<form>或在URL鏈接上的參數(shù)

          void setTitle(String)指定頁面標(biāo)題,常常在Velocity Screen模塊模板里用作第一個語句

          user getUser()得到當(dāng)前在session里的用戶

          boolean userExists()檢查在session里是否存在當(dāng)前用戶

          boolean removeUserFromSession()使當(dāng)前在session里的用戶無效

          void setRedirectUri(String ruri)為重定向(redirection)設(shè)置URL

          如何你正在Screen模塊Java類里處理信息,并且你想更改Screen模塊的模板,你可以使用getTemplateInfo()方法來獲取一個TemplateInfo對象,并且使用setScreenTemplate(String)方法來設(shè)置一個新的動態(tài)模板。

          TemplateLink對象

          在所有的Velocity模板中,你可以使用TemplateLink對象來創(chuàng)建一個新鏈接到另外一個模板,這個對象源自DynamicURI。新鏈接通過下面的代碼來加入:

          $link.setPage(String);

          $link引用是一個TemplateLink對象,它和DynamicURI一起擁有一個巨大的方法列表和用于構(gòu)建動態(tài)連接的字段。所有在我們示例中的這些鏈接都是指向一個動態(tài)頁面。我們也可以使用下面的命令鏈接到一個靜態(tài)頁面

          $link.setPage(“/docs/static/privacy.html”)

          這個新的靜態(tài)頁面是一個用戶Web瀏覽器的沒有任何導(dǎo)航或布局控件的主頁面。最后的操作是在Velocity模板里使用靜態(tài)頁面,并且維持Web應(yīng)用程序的界面。

          TemplatePageAttributes對象

          當(dāng)$page引用被用于一個Velocity模板時,TemplatePageAttributes對象被獲取。這個對象允許當(dāng)前頁面的元素被更改,比如標(biāo)題和背景顏色。比如:

          $page.setBgColor(“#FF0000”)

          這個命令將產(chǎn)生一個紅色背景,你允許通過addAttribute(string, int)命令訪問<body>標(biāo)簽。其他可用的命令包括:

          addAttribute(String name, String value)body標(biāo)簽里增加屬性 “name”“value”

          setBackground(String url)設(shè)置背景 URL.

          setDescription(String description)設(shè)置聲明(description)標(biāo)簽

          setKeywords(String description)設(shè)置一個關(guān)鍵字(keyword)標(biāo)簽

          setLinkColor(String color)指定鏈接顏色

          setStyleSheet(String url)設(shè)置一個CSSstylesheet

          setTextColor(String color)指定文本顏色

          setVLinkColor(String color)指定vlink顏色

          本章小結(jié)和下章介紹

          在本章,你了解到,在Turbine驅(qū)動的Web應(yīng)用程序的開發(fā)里,Velocity是一個主要的組件。在下一章里,我們將介紹另一個框架,名叫Maverick

          posted on 2008-10-29 11:12 KINGWEE 閱讀(2100) 評論(0)  編輯  收藏 所屬分類: Velocity

          主站蜘蛛池模板: 当阳市| 上杭县| 塔河县| 宣城市| 石景山区| 囊谦县| 河北区| 共和县| 大田县| 新丰县| 彭山县| 阿瓦提县| 汉川市| 内江市| 驻马店市| 从江县| 巫山县| 池州市| 涡阳县| 浦江县| 客服| 察隅县| 息烽县| 南城县| 沙田区| 临澧县| 井陉县| 华宁县| 海盐县| 武威市| 汶上县| 千阳县| SHOW| 滁州市| 封开县| 布拖县| 香格里拉县| 毕节市| 托克逊县| 读书| 鄂托克旗|