[Scarab] 相关技术 (Turbine/Velocity/Intake/Torque )

 
Turbine Training
(一)              Turbine 简介
1.                      概述
Turbine Apache Jakarta 项目中的一个开源的服务器端 Java 框架。任何支持 Servlet2.2 或以上规范的容器都可以运行 Turbine 应用程序。
当然, Turbine 的最大优势是免费,并且向开发人员提供全部的源代码。
Turbine 技术概述:
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
*#
 
 
 
   字符串连接示例:
 
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 中单个的域可以映射到不同的对象。
Field s 也有 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>
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值