(一) Turbine簡介
1. 概述
Turbine是Apache Jakarta項目中的一個開源的服務器端Java框架。任何支持Servlet2.2或以上規范的容器都可以運行Turbine應用程序。
當然,Turbine的最大優勢是免費,并且向開發人員提供全部的源代碼。
Turbine技術概述:
- 表示層 - Velocity or JSP
- 數據庫層(持久層) - Turbine 使用 Torque, 但是也支持其他的持久層工具,如OJB或者 Hibernate。.
- HTML 表單數據驗證使用 "Intake"-Service.
- 日志(Logging) - Turbine 使用 Commons Logging并且支持眾多的日志輸出工具,如Log4J。(注:Scarab使用Log4j,不過有些問題。), jdk14 or simple file logging
- 基于服務的框架,在Turbine2.4及以后版本中使用和Avalon框架兼容的組件。
Turibne促使基于它的應用程序遵循MVC架構。在MVC設計模式中,模型層(Model)包含了業務邏輯和存儲的數據;表示層是用戶接口;控制層負責控制應用程序的流程并且管理模型層和表示層。
Turbine有2個版本,各有優劣:
- 當你從舊的版本遷移到新的版本,或者基于Turbine框架的一個已發布版本進行項目開發的時候,應該使用Turbine2.3.2。
- Turbine2.4是將要發布的下一個版本。Turbine2.4使用了下一代技術,比如基于avalon的容器和從Turbine的姊妹項目Fulcrum中分離出來的組件。如果你不介意自己從Subversion中取出代碼打成jar包,并且可以忍受框架開發過程中所做出的偶爾的修改,那么你應該使用這個版本。
2. 關于Turbine3.0 (Scarab用的Turbine版本)
Turbine3.0是Turbine的一個試驗版本。從內部來說,它和Turbine2.x有很多不同。它使用了一個Catalina式的Pipeline(通過這個Pipeline可以很容易地對處理流程進行細類度[fine-grained]的控制),并且做了許多提高和簡化。
雖然這個版本叫做3.0,但是不應當把它看作是Turbine的下一個或者未來的版本。開發這個版本的最初目的確實是把它作為下一個主要版本,不過,開發已經停止。這個版本中超前于當前Turbine版本的不同設計之處正在逐漸遷移回來。
Turbine3.0不再進行開發,開發重點已經轉移到Turbine2.4。目前針對Turbine3.0的各種各樣的改動是為了使人們更容易的遷移到Turbine2.4,重點是把Scarab遷移到Turbine2.4。
這當中涉及到把使用commons-xo的pipeline改為使用XStream;添加Yaafi,一個Avalon組件服務;遷移到許多發布的Fulcrum Avalon組件等等。
3. Turbine服務簡介(Turbine是基于服務的框架)
服務(Services)在Turbine框架中都是單例的(singleton),并且是可插入式的實現,能夠在Turbine啟動和關閉的時候進行初始化和關閉。
① 服務的特征:
Ø 單例(singleton) – 在系統中只有一個實例。內存和連接都只分配一次,內部狀態對于所有的客戶端來說是共同的。
Ø 插入式實現 – 需要的話可以使用自己的實現,只要改變配置文件TurbineResources.properties中的相關記錄就可以了。
Ø 能夠在系統啟動的時候訪問ServletConfig,處理相對路徑以及諸如此類的操作。
Ø 能夠在第一次執行doGet方法的時候訪問RunData,取得當前的URL以及諸如此類的信息。
Ø 能夠在客戶端第一次請求該項服務之前初始化自己(分配內存,建立連接)。應用程序從來沒有用到的服務不會分配資源。
Ø 能夠在系統關閉的時候執行某些動作,比如關閉打開的連接。
② 服務的生命周期:
服務的生命周期開始于服務的構造器。一項服務不應當在構造器中做很多事情,尤其是許多耗費系統資源的事情,比如分配很大的內存,建立DB或者網絡連接等等。服務可能存在于properties配置文件中,但是除非一個客戶端用到了某個服務,否則沒有必要起動這項服務。
Early initialization 和構造器類似。用來傳遞一些服務可能會用到的信息。Early initialization 方法應當處理配置信息,存儲一些值,但是不應當分配資源。因為仍然有可能這項服務不會被用到。如果服務可以使用了(不再需要傳給它任何對象),也不需要在late initialization 過程中分配資源,那么可以更改內部狀態以便使getInit方法返回true。
當系統第一次請求某項服務時,該服務才進行Late initialization,分配需要的資源,然后更改內部狀態以便使getInit方法返回true。如果初始化之后,getInit方法仍然返回false,那么這項服務就出問題了。
Late initialization之后,服務就做好干活的準備了。
當不再需要某項服務的時候(通常是系統關閉的時候),調用shutdown方法,釋放所有資源。如果發生錯誤,那么這些錯誤會被忽略。
Turbine服務相關類一般放在org.apache.turbine.services 包中。
注:
Turbine包結構對比

Turbine2.4中提供了許多默認服務,services包下有20多個子包;
Turbine3.0中就少多了,services包下只有pull/rundata/yaaficomponent 3個子包。不過在org.apache.fulcrum有4個子包,也是提供服務的,應該是使用了fulcrum項目的東西。
補充:Fulcrum項目簡介
i. Fulcrum概述
Fulcrum最初是作為Turbine3的一部份進行開發的,目的是把服務從Turbine2中分離(decouple)出來,使它們在2個項目中都可以使用。
Fulcrum現在逐漸演化為一個基于Avalon框架的組件庫。每個服務都正在被轉化為一個獨立的組件,各自獨立發布。這使得Turbine項目可以在某個組件更改后單獨發布它,而不必一次發布整個框架。同時,其它的項目可以也利用這些組件。
ii. 容器兼容性
所有的組件兼容于Avalon的ECM容器。任何對于其他組件,系統屬性,或者上下文元素的依賴都記錄在每個組件各自的文檔里。
而且,Fulcrum提供了Yaafi組件。Yaafi (Yet Another Avalon Framework Implementation)是一個簡易容器,用于和單例組件(singleton components)一起使用。Yaafi非常適合用于對你的組件進行單元測試。通過之后,你的組件就可以運行在任何Avalon容器中,如ECM,Phoenix,Excaliber,等等。
iii. Fulcrum組件列表(紅色組件在Scarab中有應用)
Released Components
- BSF
- Cache
- Crypto
- DVSL
- Factory
- Localization
- Mimetype
- Pool
- Naming
- OSWorkflow
- Quartz
- Security
- Test Container
- Upload
- XMLRPC
- XSLT
- YAAFI
Sandbox Components
- Script
- CommonsEmail
- PBE
- Groovy
- ResourceManager
- Configuration
- HsqlDB
- Intake
- Parser
- Template
Howtos (old)
- JSP Service
- Template Service
- Velocity Service
4. Turbine配置簡介(作為控制器)
① web.xml文件的配置
正常配置,只有一點需要注意一下,即Servlet的初始化參數可以指定2種文件:
a) 使用參數名為 "configuration"的配置文件:
//
// <init-param>
// <param-name>configuration</param-name>
// <param-value>/WEB-INF/conf/turbine.xml</param-value>
// </init-param>
//
// 加載XML配置文件。
//
b) 使用一個名為"properties"的配置文件:
//
// <init-param>
// <param-name>properties</param-name>
// <param-value>/WEB-INF/conf/TurbineResources.properties</param-value>
// </init-param>
//
// 加載屬性(.properties)文件。
//
//如果未使用a或者b的方式設置的話,Turbine 默認加載相對于應用程序根目錄下的 /WEB-INF/conf/TurbineResources.properties 文件。
注:Scarab中使用XML配置文件。其中可以指定多個properties文件。
② TurbineResources.properties
顧名思義,這個文件中配置了關于Turibne框架的配置信息。從目前掌握的情況來看,以下幾項是必須的配置:
a. M O D E
只有一項設置:
turbine.mode = standalone
可選的值為:standalone, integrated
指定Turbine是作為控制器,還是集成組件。
b. R E S O L V E R
指定使用什么Resolver來找到modules和templates。
c. R E S O L V E R C A C H I N G
指定modules和templates是否緩存。
d. M O D U L E P A C K A G E S
這是Turbine的“classpath”。如果自定義modules的話,需要在這里指明路徑。
有兩點需要特別指出:
Ø 一是Turbine的pipeline配置文件在此處指定。
pipeline.default.descriptor = WEB-INF/conf/scarab-pipeline.xml
這個描述文件中指出了pipeline中含有哪些Values。
Ø 二是默認框架頁面也應該是在這里指出的:
template.default = /Default
template.default.extension = vm
e. F R A M E W O R K S E T T I N G S
這部分是關于控制框架行為的設置,比如默認templates和screens,session管理,等等。
f. S E R V I C E S
定義為Turbine提供服務的類。(注:我認為可以理解為注冊服務)
格式: services.[name].classname=[implementing class]
e.g. :services.IntakeService.classname=org.apache.fulcrum.intake.TurbineIntakeService
指定一項服務的屬性使用如下的與法:
service.[name].[property]=[value]
另外,服務在這里的注冊順序就是服務的初始化順序,不可以隨意改動,因為有的服務需要依賴于其他的服務。
g. 具體Services配置
配置某個服務自己的配置。
注:配置文件中有關于配置的簡單說明。
警告:上述配置未全部經過嚴格驗證。
5. Scarab Services淺析
在Scarab使用的Turbine配置文件TurbineResource.properties中配置了下述服務:
Øservices.YaafiComponentService.classname=org.apache.turbine.services.yaaficomponent.TurbineYaafiComponentService
Øservices.SecurityService.classname=org.tigris.scarab.services.security.ScarabDBSecurityService
Øservices.TemplateService.classname=org.apache.fulcrum.template.TurbineTemplateService
Øservices.RunDataService.classname=org.apache.turbine.services.rundata.TurbineRunDataService
Øservices.PullService.classname=org.apache.turbine.services.pull.TurbinePullService
Øservices.IntakeService.classname=org.apache.fulcrum.intake.TurbineIntakeService
# Turn on the appropriate template service.
Øservices.VelocityService.classname=org.apache.fulcrum.velocity.TurbineVelocityService
Øservices.EmailService.classname=org.tigris.scarab.services.email.VelocityEmailService
配置為org.apache.turbine.*的,使用的是Turbine3.0提供的默認服務;
配置為org.tigris.scarab.*的,應該是Scarab自行實現的服務;
配置為org.apache.fulcrum.*的,原意應該是使用已經分離到Fulcrum中的組件。
前面提到過,Fulcrum最初是作為Turbine3的一部份進行開發的,目的是把服務從Turbine2中分離(decouple)出來,形成單獨的組件,以便對每個組件進行版本升級和復用。從Turbine3.0框架的結構來看,顯然是取消了大部分Turbine框架提供的默認服務,代之以Fulcrum中的組件。不過,顯然開發組在按照這個想法進行開發的時候,因某種變故改變了計劃,取消了Turbine3.0的開發。
根據Scarab的配置文件以及Fulcrum的文檔可以確認,TemplateService和VelocityService使用的是舊的Fulcrum配置,可能是早期Fulcrum項目的成果。其中,TemplateService已經在Fulcrum中有新的組件,但是在Scarab中沒有采用(Turbine2.4中采用了);而Velocity是Apache Jakarta的子項目,也就是和Turbine項目平級。根據Velocity的文檔來看,Velocity在開發Turbine的時候就已經作為Turbine的主要頁面語言,而且很多Velocity的開發者參與了Turbine框架的開發。因此,Velocity在Turbine框架中的使用方法不同于其它框架。
IntakeService在Scarab中的使用也有一點特殊。這里,IntakeService是作為一項獨立的服務在TurbineResources.properties中配置;而在Turbine2.4中,IntakeService是作為一個Avalon Component進行配置的。
(二) Velocity
1. 簡介
Velocity是基于Java的模版引擎(template engine)。它允許任何人使用簡單但是功能強大的模版語言引用在Java代碼中定義的對象。
當使用Velocity進行Web開發的時候,通過MVC模式,網頁開發者和Java程序員可以平行工作開發web網站,這意味著網頁設計者可以完全將注意力集中于網站的視覺效果,而程序員完全將注意力集中于后臺程序開發。Velocity將Java代碼和網頁分離開,增強了網站在其生命周期內的可維護性,提供了一種除了JSP或者PHP之外的可行選擇。
Velocity的用途不僅局限于web領域;比如說,它能夠用來從模版中生成SQL,PostScript和XML。它既可以作為獨立的工具用來生成源代碼和報告,也可以作為其他系統的集成組件。舉個例子,Velocity為Turbine應用程序框架提供模版服務(template service),并且一起構成了一個視圖引擎,通過真正的MVC模型簡化了web應用程序的開發。
2. VTL(Velocity Template Language)語法簡介:
1) 概述
VTL提供了一種在頁面中和動態內容交互的最容易,最簡潔的方法。即使一個沒有編程經驗的頁面開發人員也可以很快地學會在頁面中使用VTL和動態內容交互。
VTL使用“引用(references)”來把動態內容嵌入到頁面中,一個變量(variable)就是引用的一種。變量能夠引用在Java代碼中定義的東西,或者在頁面的VTL語句(statement)中賦值。下面是一個可以嵌入到HTML文檔中的VTL語句的例子:
#set( $a = "Velocity" )
和所有的VTL語句一樣,這個VTL語句以“#”開頭,包含了一個標識符(directive):set。當客戶端請求一個頁面的時候,Velocity Templating Engine 會搜索整個頁面,找到所有的“#”,然后決定哪些“#”標志著VTL語句的開始,哪些“#”與VTL無關。
“#”后面跟著一個標識符,set。這個set標識符使用了一個表達式(包含在括號中)——一個給變量賦值的等式。這個變量位于左邊,值位于右邊;中間由一個等號分隔。
在上面的例子中,變量是$a,其值是“Velocity”。和所有的引用一樣,這個變量以“$”開頭。值總是位于括號中;Velocity中關于數據類型不會有任何混亂,因為只有strings(文本信息)可以賦給變量。下面的經驗之談可能更有助于理解Velocity是如何工作的:引用以“$”開頭,用來取得值;標識符以“#”開頭,用來做某些事情。(References begin with $ and are used to get something. Directives begin with # and are used to do something.)。在上面的例子中,#set用來給變量賦值。然后,就可以在頁面中使用變量$a輸出“Velocity”了。
2) 基本語法
① 引用標識符“$”用來引用變量,屬性,方法。
變量:
· Normal notation: $mud-Slinger_9
· Silent notation: $!mud-Slinger_9
· Formal notation: ${mud-Slinger_9}
屬性:
· Regular Notation: $customer.Address
· Formal Notation: ${purchase.Total}
方法:
· Regular Notation: $customer.getAddress()
· Formal Notation: ${purchase.getTotal()}
· Regular Notation with Parameter List: $page.setTitle( "My Home Page" )
② 指示標識符“#”用來標識控制語句
A) #set標識符用來給引用賦值。可以把值賦給一個變量,也可以賦給一個屬性。賦值過程位于括號中,如下所示:
#set( $primate = "monkey" )
#set( $customer.Behavior = $primate )
表達式左側(left hand side [LHS])是一個變量或者屬性;
右側(RHS)是下述類型中的一種:
¨ Variable reference
¨ String literal
¨ Property reference
¨ Method reference
¨ Number literal
¨ ArrayList
下面是上述每種類型的例子:
#set( $monkey = $bill ) ## variable reference
#set( $monkey.Friend = "monica" ) ## string literal
#set( $monkey.Blame = $whitehouse.Leak ) ## property reference
#set( $monkey.Plan = $spindoctor.weave($web) ) ## method reference
#set( $monkey.Number = 123 ) ##number literal
#set( $monkey.Say = ["Not", $my, "fault"] ) ## ArrayList
注意:在最后一個例子中,在[ ]中定義的元素可以使用ArrayList類的方法進行訪問。所以,舉例來說,你可以使用$monkey.Say.get(0) 來取得其中的第一個元素。
B) Conditionals
n If / ElseIf / Else
#if用來進行條件判斷,比如:
#if( $foo )
<strong>Velocity!</strong>
#end
根據變量$foo的值來決定條件是否為真,有下述兩種判斷方式:(i) $foo是布爾型,其值為true;(ii) $foo的值不為null。記住,Velocity上下文中只含有對象,所以當我們說“boolean”的時候,意味著一個Boolean對象。即使對于返回值為true的方法也是這樣——內部機制會決定返回值是一個對應的Boolean對象。
#elseif或者#else元素可以和#if元素一起使用。注意,Velocity Templating Engine 會在第一個條件為真的地方停止執行。在下面的這個例子中,假設$foo的值為15,$bar等于6 :
#if( $foo < 10 )
<strong>Go North</strong>
#elseif( $foo == 10 )
<strong>Go East</strong>
#elseif( $bar == 6 )
<strong>Go South</strong>
#else
<strong>Go West</strong>
#end
$foo大于10,所以前兩個條件為false。下一步比較$bar的值是否為6,返回true,所以輸出結果為Go South.
請注意,現在,Velocity的數字比較僅限于Integers – 任何其它的類型都會返回false。唯一的例外是“==”,Velocity要求“==”兩邊的對象必須是同一種類型。
n 關系和邏輯運算符
Velocity使用等號運算符決定變量之間的關系。請看下面的例子:
#set ($foo = "deoxyribonucleic acid")
#set ($bar = "ribonucleic acid")
#if ($foo == $bar)
In this case it's clear they aren't equivalent. So...
#else
They are not equivalent and this will be the output.
#end
Velocity也有邏輯AND, OR and NOT運算符。下面是使用方法示例:
## logical AND
#if( $foo && $bar )
<strong> This AND that</strong>
#end
## logical OR
#if( $foo || $bar )
<strong>This OR That</strong>
#end
##logical NOT
#if( !$foo )
<strong>NOT that</strong>
#end
需要注意的一點是,不要把( !$foo )和($!foo )搞混了。
C) Loops
n Foreach Loop
示例:
<ul>
#foreach( $product in $allProducts )
<li>$product</li>
#end
</ul>
這個loop循環遍歷了List對象 $allProducts。每次循環,取出$allProducts中一個對象,賦給變量$product。
變量$allProducts是一個Vector,Hashtable或者 Array。賦給變量$product的是一個Java對象,可以使用$product來引用這個對象。比如說,如果$product是一個
Product
對象,可以通過
$product.Name (或者$Product.getName())方法取得這個
Product
的名稱。
假設$allProducts是一個Hashtable。如果想要取得這個Hashtable中的所有的key和value,可以這樣:
<ul>
#foreach( $key in $allProducts.keySet() )
<li>Key: $key -> Value: $allProducts.get($key)</li>
#end
</ul>
Velocity提供了一種簡便方法取得循環計數值以便做點什么,比如:
<table>
#foreach( $customer in $customerList )
<tr><td>$velocityCount</td><td>$customer.Name</td></tr>
#end
</table>
循環計數變量的默認名稱為$velocityCount,是在配置文件velocity.properties中指定的。默認情況下,其值從1開始,可以在配置文件中重新指定起始值。
下面是循環計數屬性的配置方法:
# Default name of the loop counter
# variable reference.
directive.foreach.counter.name = velocityCount
# Default starting value of the loop
# counter variable reference.
directive.foreach.counter.initial.value = 1
D) Velocimacros
#macro腳本元素使模版設計者(template designers)能夠定義一段重復的段落(segment)。Velocimacros用途很廣泛。下面這個Velocimacro簡要表現了其概念:
#macro( d )
<tr><td></td></tr>
#end
這個Velocimacro叫做d ,可以象使用其它VTL標識符那樣來使用Velocimacro:
#d()
當這個模版被請求的時候,Velocity會用包含單個空數據單元的行替代 #d() 。
一個Velocimacro可以帶有任意個參數 – 也可以如上例所示沒有參數 – 但是當調用Velocimacro的時候,參數個數必須和定義的一致。下面這個Velocimacro有2個參數,一個color和一個array:
#macro( tablerows $color $somelist )
#foreach( $something in $somelist )
<tr><td bgcolor=$color>$something</td></tr>
#end
#end
上例中的Velocimacro名為tablerows,有2個參數:$color和$somelist。
任何可以放入VTL模版中的語句都可以放入Velocimacro中。Velocimacro tablerows 是一個foreach語句。在這個Velocimacro的定義中有2個#end語句:第一個和#foreach對應;第二個表示Velocimacro定義的結束。
#set( $greatlakes = ["Superior","Michigan","Huron","Erie","Ontario"] )
#set( $color = "blue" )
<table>
#tablerows( $color $greatlakes )
</table>
注意,當調用Velocimacro#tablerows的時候,第二個參數為$greatlakes,輸出結果如下:
<table>
<tr><td bgcolor="blue">Superior</td></tr>
<tr><td bgcolor="blue">Michigan</td></tr>
<tr><td bgcolor="blue">Huron</td></tr>
<tr><td bgcolor="blue">Erie</td></tr>
<tr><td bgcolor="blue">Ontario</td></tr>
</table>
Velocimacros的參數可以是如下類型的VTL元素:
· Reference : anything that starts with '$'
· String literal : something like "$foo" or 'hello'
· Number literal : 1, 2 etc
· IntegerRange : [ 1..2] or [$foo .. $bar]
· ObjectArray : [ "a", "b", "c"]
· boolean value true
· boolean value false
當把引用作為參數傳給Velocimacros的時候,請注意是引用傳遞。這意味著其值是在Velocimacro中每次使用到的時候才產生的。這個特點允許你傳進去一個帶有方法的引用,每次使用的時候才調用該方法。如下所示:
#macro( callme $a )
$a $a $a
#end
#callme( $foo.bar() )
執行結果,引用$foo的方法bar()被調用了3次。
如果你需要回避這個特點的話,可以每次先取出方法的執行結果,然后把它傳進去:
#set( $myval = $foo.bar() )
#callme( $myval )
③ 注釋標識符
Ø單行注釋:
## This is a comment.
Ø多行注釋:
#*
This is a multiline comment.
This is the second line
*#
This is a multiline comment.
This is the second line
*#
④ 字符串連接示例:
例1:
#set( $size = "Big" )
#set( $name = "Ben" )
The clock is $size$name.
輸出結果:
The clock is BigBen.
例2:
#set( $size = "Big" )
#set( $name = "Ben" )
#set($clock = "$size$name" )
The clock is $clock.
輸出結果:
同上例。
例3:
最后一個例子,如果想把“靜態”字符串和引用混合輸出,必須使用'formal references':
#set( $size = "Big" )
#set( $name = "Ben" )
#set($clock = "${size}Tall$name" )
The clock is $clock.
輸出結果:
The clock is BigTallBen.
(三) Intake Service
1. 簡介
Intake使用XML規范驗證form提交的數據,并且把這些數據映射到bean屬性中。換句話說,Intake允許web應用程序獲得form提交的數據,驗證數據,然后把這些數據映射到一個對象中。類似Torque的工具在對象和數據庫之間建立映射,而Intake則在對象和form數據之間建立映射。Intake可以在一個支持Avalon組件的應用程序中單獨使用。不過,Intake最適用于Turbine框架。
使用Intake有若干優勢。首先,Intake提供了一個處理表單數據的集中管理系統。所有Intake的配置都在一個專門的XML文件(Intake.xml)中完成。其次,Intake便于驗證表單數據。Intake能夠進行表達式匹配以便保證表單域中包含合法的數據。比如說,如果某人應當在一個表單域中填入數字,填入內容可以用一個合格的表達式進行驗證。最后,Intake能夠把錯誤信息集中到一起。如果驗證失敗,定義在XML文件中的錯誤信息將被顯示給用戶。
2. 概念
示例Intake.xml文件:
<?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?>
<input-data basePackage="com.neusoft.">
<group name="Login" key="Login" mapToObject="beans.TurbineUser">
<field name="Name" key="name" type="String" mapToProperty="Name">
<rule name="required" value="true">Name is required.</rule>
</field>
<field name="Password" key="pwd" type="String" mapToProperty="Pwd" >
<rule name="required" value="true">Password is required.</rule>
</field>
</group>
</input-data>
Group是已經賦值的一組域,他們形成了一個邏輯單元。
示例中Login這個group包含了一些域,它們和數據對象bean.TurbineUser中的成員變量相對應。同時,數據對象中的成員變量需要有相應的setter/getter方法。注:Group中的域必須有相應的數據對象中的成員變量與其對應;而數據對象中的成員變量可以多于group中的域。
每個Group有一個name屬性,在頁面代碼和servlet代碼中就是通過這個值來引用相應的group對象。每個Group還有一個key屬性,這個屬性不會在代碼中用到,只要保證它在整個配置文件中是唯一的就可以了。
Group的域所映射的數據對象也可以指定。這里有一個默認值,而一個group中單個的域可以映射到不同的對象。
Fields也有name和key屬性,功能和group的類似。屬性mapToObject和mapToPropertiy用來映射group對象和數據對象(JavaBean),并且在成功驗證之后,把字段數據賦到bean中。每個字段必須有一個類型,可以是諸如String和Integer的簡單類型。
Field可以定義rule元素。可以定義的rule包括最大/小值,長度,值的范圍等等。
<field name="TypeId" key="typeid" type="int">
<rule name="mask" value="[0-9]+">intake_BadIdMessage</rule>
</field>
<rule name="minLength" value="1">intake_AttributeNameNotAllowedEmpty</rule>
<rule name="maxLength" value="255">MustBeLessThan255Characters</rule>
(四) Torque
1. 簡介
Torque是一個持久層框架,原來包括在Turbine框架中,從Turbine2.2開始Torque被分離出來作為DB項目下的一個單獨的子項目。目前最高版本是3.2。
Torque是面向Java的對象-關系轉換器。換句話說,Torque使你能夠使用Java對象來訪問和操縱關系型數據庫中的數據。和大多數對象-關系轉化器不同的是,Torque不是使用反射來訪問用戶提供的類,而是根據描述數據庫層次的XML Schema(可以是手寫的,也可以是根據已存在的數據庫生成的)生成必須的類(包括數據對象)。XML Schema也可以用來生成和執行創建數據庫中的所有表的sql語句。
轉載:
對持久層以及持久層框架的理解
所謂持久層就是在整個系統中與持久存儲介質如Database,LDAP Server,XML等打交道的部分。持久層框架的作用就是使持久層訪問持久介質更加方便。如果是為了訪問Database而建立的持久層框架那么就又有一個O/R Mapping的概念。O/R Mapping就是建立對象(Object)與關系數據庫(R)中的表(不一定是一對一)的映射。Torque就是這樣一種起到O/R Mapping作用的持久層框架。他使java程序員可以方便地通過操作普通java對象的方式來訪問數據庫,甚至不用了解數據庫的相關知識(最好是了解),另一個好處是屏蔽數據庫類型即可任意更換持久層框架支持的Database。
Torque的工作原理
一般在利用O/R Mapping框架進行開發的時候,有三個基本的單元即關系數據庫中的表(Table),Java中的持久對象(PO),定義PO到Table映射的xml文件(Schema)。
首先,Torque包含一個generator用來根據由開發者配置好的Schema來自動生成PO和Table,這就意味著開發者只要定義好Schema,PO和Table就可以自動生成了。
在生成好的PO和Table以后,開發者就可以利用PO來進行對Table的訪問了。為了達到這個目的Torque提供了一個運行時環境來保證代碼的正確運行。在工程中引入了torque相關的.jar就可以擁有這個運行環境了。
2. Torque的元素
Torque由多個部分構成:
Ø runtime
Torque runtime 包含了在應用程序中操作數據庫所需的一切。這是應用程序中需要的唯一的Torque組件,可以單獨使用。
Ø generator
Generator含有一些ant task,供Maven插件使用。如果使用Maven的話,不需要直接操作generator。不過,也可以直接使用ant調用generator。
Ø maven-plugin
Maven plugin 創建了用來訪問和存儲數據庫信息的O/R peer和object類。它也可以生成已存在數據庫的XML描述文件,或者反過來,生成SQL腳本來創建數據庫中的表。從內部來說,Maven plugin使用generator來實現這些任務。
Ø templates
模版含有構建塊(building blocks),供generator使用來創建O/R peer 和 object類,SQL 腳本以及諸如此類的東西。如果你想改變generator的輸出結果的話,可以通過改變模版來實現(只有在其特殊的情況下才需要這樣做)。3.1.x及以前版本,模版都是generator的一部分。從Torque3.2開始,模版已經被分離到了自己的jar包中。
3. 主要Runtime classes介紹:
Peers
① Peers中的一切都轉換到了Peer類中。一個Peer類和一個數據表對應。你可以使用和某個數據表相對應的Peer類來操作這個表。Peer類都是自動生成的。
② Peer類只含有靜態方法,所以不必創建任何Peer類對象。由于和表的關系是一一對應的,所以在這個層次上沒有必要創建對象。
③ Peer類都是自動生成的。每個表生成2個Peer類:“Base表名Peer”類和“表名Peer”類。“Base表名Peer”類包含了所有功能,并且不應該進行任何改動;“表名Peer”類是“Base表名Peer”類的子類,初始時是空的,可以添加或者更改方法以提供需要的功能。如果使用Torque重新生成Peer類,只有“Base表名Peer”類中的代碼發生改變,已有的存在于“表名Peer”類中的代碼仍然可以使用。
Data Objects
① 一個數據對象保存了一個表中的一行數據。數據對象是自動生成的。它以Bean屬性的形式保存了表中的每個字段。
② 數據對象類也是自動生成的。每個表對應生成2個數據對象類:“Base<table-name>”和“<table-name>”。功能和使用方法與Peer類相似。
③ 數據對象是由和其相關聯的Peer類以幾乎獨占的方式使用的。Peer類把表包裝了起來,而數據對象把表中的單行數據包裝了起來。二者往往聯合使用。
④ 數據對象有2種使用方式。最常用的方式是在調用一個Peer類的doSelect方法之后使用數據對象抽取數據。doSelect方法返回一個含有數據對象的List,其中包含了查詢結果集(Resultset)中的數據。第二種方式是創建數據對象,然后調用該對象的save方法來把相關的行插入或者更新到數據庫中。
Criteria
① Criteria是對一個sql查詢條件的抽象。我們使用criteria對象來指定一個sql語句的查詢條件。數據庫調節器類(adaptor classes)包含了如何轉換criteria對象以便適應不同的數據庫的信息。
② Criteria從作用上來說是構成一個查詢條件的字段名稱和值的映射。默認的運算符是“=”,但是也可以自己定義運算符(<, >, <=, > =, IN, etc.)。
③ Creteria也能用來做其它的查詢,如ORDER BY或者DISTINCT。如果Criteria不能滿足你的要求的話(這種情況不應經常發生),你仍舊可以使用原始的sql語句進行查詢。
4. 使用方法簡介:
主要涉及到Runtime classes中的Peers,Data Objects和Criteria。
① Peer類都是自動生成的。每個表生成2個Peer類:“Base表名Peer”類和“表名Peer”類。需要重寫,或者添加新的方法的時候,都在“表名Peer”類中進行,不要修改Base表名Peer”類。“
② Peer類只含有靜態方法,所以不必創建Peer類對象。任何
③ 每個表對應生成2個數據對象類:“Base<table-name>”和“<table-name>”。功能和使用方法與Peer類相似。
④ 一個數據對象保存了一個表中的一行數據。數據對象是自動生成的。它以Bean屬性的形式保存了表中的每個字段。可以作為bean來使用。
⑤ 數據對象有2種使用方式:
1) 最常用的方式是在調用一個Peer類的doSelect方法之后使用數據對象抽取數據。doSelect方法返回一個含有數據對象的List,其中包含了查詢結果集(Resultset)中的數據。
2) 第二種方式是創建數據對象,然后調用該對象的save方法來把相關的行插入或者更新到數據庫中。
⑥ Criteria中包裝了sql語句。在進行數據庫操作的時候需要傳遞一個Criteria對象給相關Peer類中方法。
比如:
Criteria criteria = new Criteria();
List authors = AuthorPeer.doSelect(critieria);
上述語句取出Author表中的所有數據,相當于sql語句:
Select * from Author
關于Criteria的詳細使用方法,參見:
操作數據庫的詳細例子,參見:
http://db.apache.org/torque/releases/torque-3.2/tutorial/step5.html
(五) Turbine Sample
1. Login頁面主要代碼注解:
① 指定處理頁面的Action:
<input type="hidden" name="action" value="Login" />
② 指定action中處理頁面的具體方法:
<input type="submit" value="submit" name="eventSubmit_doLogin" tabindex="2" />
此處,提交按鈕name屬性的命名方式是固定的,即必須有一個前綴eventSubmit,加上一個下劃線“_”,然后是具體的方法名稱。在對應的action中,方法的命名也是doXXX。其中,do后面的第一個字母大寫,其余的均小寫。
③ 指定跳轉的目標頁面:
<input type="hidden" name="nextTemplate" value="success.vm" />
④ 取得對應的Intake group對象:
#set ($login = $intake.Login.default )
其中,$intake是內置的Intake對象,可以直接在頁面中使用;Login是在intake.xml中配置的group名稱。通過該語句得到了一個group對象$login。
⑤ 把表單中的字段映射到相應的group域中
<input name= "$login.Name.Key" value="$!login.Name" size="25" type="text"/>
<input name= "$login.Password.Key" value="$!login.Password" size="25" type="text"/>
⑥ Intake根據配置文件中每個field定義的rule進行入力數據校驗。如果驗證未通過,則顯示rule指定的錯誤信息。
#if ( !$login.Name.isValid() )
$login.Name.Message<br>
#end
<br>
#if ( !$login.Password.isValid() )
$login.Password.Message<br>
#end
⑦ 指定提交的頁面名稱,如果驗證未通過,返回setPage方法指定的頁面:
<form action="$link.setPage("Login.vm")" method="post" name="login">
此處仍存在問題,需要進一步調查。
2. Login.java主要代碼注解:
① 處理頁面請求的方法一般都有2個參數,RunData和TemplateContext。
RunData是Turbine的一個接口,儲存了一些運行時的數據。
TemplateContext提供了對Context的操作
② 在Servlet中取得Intake對象:
IntakeTool intake = (IntakeTool) getTool(context,ScarabConstants.INTAKE_TOOL);
IntakeTool是Intake的子類,一般使用的Intake對象都是IntakeTool對象。
③ 校驗輸入的數據:
intake.isAllValid()
④ 取得頁面中指定的下一頁面:
String nextTemplate = data.getParameters().getString(ScarabConstants.NEXT_TEMPLATE);
⑤ 設置跳轉的目標頁面:
setTarget(data, nextTemplate);
通過setTarget方法來指定下一頁面;可以根據不同情況指定不同的目標頁面。
⑥ 取得表單對應的group對象
Group login = intake.get("Login", IntakeTool.DEFAULT_KEY);
⑦ 取得某個表單字段:
String username = login.get("Name").toString();
⑧ 把表單中的數據映射到對應的對象中:
login.setProperties(user);
⑨ 特別說明:
context.put("loginuser",user);
此處僅做示例用。
為了方便使用,把一個bean對象放在了context中,以便目標頁面可以直接從context中取得這個對象,驗證程序的正確性。
3. 目標頁面success.vm主要代碼注解:
① 顯示登陸用戶的信息:
$loginuser.Name
參考資料:
Apache網站:
http://www.apache.org/
Turbine主頁:
http://jakarta.apache.org/turbine/
Intake Service使用說明:
http://jakarta.apache.org/turbine/fulcrum/fulcrum-intake/howto.html
velocity主頁:
http://jakarta.apache.org/velocity/
torque主頁:
http://db.apache.org/torque/
附:
web.xml文件:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">
<web-app>
<display-name>Scarab Bug Tracker</display-name>
<description>Scarab Bug Tracker</description>
<servlet>
<servlet-name>turbine</servlet-name>
<servlet-class>org.apache.turbine.Turbine</servlet-class>
<init-param>
<param-name>properties</param-name>
<param-value>
/WEB-INF/conf/TurbineResources.properties
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>turbine</servlet-name>
<url-pattern>/issues/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1358991