Layout
相当于
Screen
、
Navigation
的容器。负责页面的布局控制。
模板化
Layout
,实际上就是以
.vm
文件作为
Layout
模板,使用
Velocity
来进行页面布局控制。
我们已经在
2.2
节中见到过一个
Layout
的模板。可以看到,在这个模板文件中,没有包含任何可显示的数据,仅有的都是一些用来控制布局用的
HTML
元素。
Okay
,相信聪明的你都明白我将要说什么了:
Layout
模板相当于一个有着很多的格子的盒子。而我们唯一需要做的,就是把
Navigation
、
Screen
等这些“插件”放到这些格子里去。此时,
Layout
就相当于表述层中的
Controller
。写到这里,我不禁为
Turbine
开发者如此的用心良苦表示钦佩与感谢。
在上一节中,我们已经用
Velocity
制作了一个简单的
Screen
。除了需要将基类换为
VelocityOnlyLayout[i]
以外,使用
Velocity
编写
Layout
的步骤跟
Screen
是完全一样的。
Layout
模板文件放置在“
TEMPLATES-PATH/layouts/
”目录下。
现在,让我们再来看一下
2.2
节中
Layout
模板里的几个主要变量:
l
$screen_placeholder
-
非常重要的一个变量。这个变量放置的地方就是
Screen
将要被输出的地方。这个变量里填充的就是保存在
String
对象里的
Screen
文本信息。
l
$navigation
-
这个变量是用来取得
Navigation
的。它的对象类型是:
org.apache.turbine.util.template.TemplateNavigation
。
l
$data
-
不用多说,就是
RunData
J
。
Navigation
的
Velocity
实现方式跟
Screen
、
Layout
完全一致。
Navigation
模板放置的地方为:“
TEMPLATES-PATH/navigations/
”目录。可以使用的基类为:
VelocityNavigation
。
当浏览器中输入的
URI
中包含
Action
参数,即类似这样时:
http://www.server.com/servlet/Turbine/template/HelloWorld.vm/action/UpdateWorld
Action
将会被触发并执行。
此时,
Turbine
按照以下顺序执行:
首先,位于“
WEB-INF/classes/com/yourcompany/app/modules/actions/
”下的
UpdateWorld class
将会被执行;随后,执行
HelloWorld class
(如果存在的话);最后,执行
HelloWorld.vm
。
Action
是一个执行特定事务的模块。这些事务可能是发一封
mail
,也可能是操作数据库,或其他可能的事务。
Action
执行结束后不返回任何值,仅有可能通过
RunData.setMessage()
方法在
RunData
中放置一条
Message
。但是,在
Action
的事务处理过程中,有可能改变或中断即将被执行的
Template
和
Screen
。
Velocity
同样提供了对
Action
的支持,但与上面提到的三个模块(
Screen
、
Layout
、
Navigation
)不同的是,
Action
不需要编写对应的模板文件。下表就是一个简单的
Action
:
package com.yourcompany.app.modules.actions;
// Velocity Stuff
import org.apache.velocity.context.Context;
// Turbine Stuff
import org.apache.turbine.util.RunData;
import org.apache.turbine.modules.actions.VelocityAction;
public class AddUser extends VelocityAction
{
public void doPerform( RunData data, Context context ) throws Exception
{
if ( data.getParameters().getString("username",null) == null)
{
data.setMessage("Username does not exist");
setTemplate ( data, "AddUser.vm" );
return;
}
// store user info into database
data.setMessage("Information stored!");
setTemplate( data, "MainMenu.vm");
// stuff something into the Velocity Context
context.put ("variable", "foo");
}
}
|
它检查提交的数据中是否包含“
username
”变量。如果不包含的话,将切换到“
AddUser.vm
”模板,并显示了一个错误提示。否则,转换到“
MainMenu.vm
”,并显示相应的提示信息,除此之外,还在
Velocity Context
中放入了一些数据。
3.3.4.1 Velocity Action Event
上面只是
Action
的一个简单用法,
Turbine
还提供一种机制,就是
Action Event
。通过
Action Event
机制,
Turbine
提供了一种非常便利的处理
form submission
的方法,使得我们可以更快速的开发
Turbine
应用。
为了明白
Action Event
机制的原理,我们先复习一下
Turbine
的相关内容
J
:
当
Turbine
接受到一个包含
Action
请求的
URI
时,首先执行这个
Action
,然后……噢,对的,就是这样。然而,对于那些继承自
ActionEvent
的类来说,在这个
Action
被执行时,发生了一些奇妙的事……
给大家留个悬念先,让我们来看一下代码
J
:
public class NewUserFoo extends VelocityAction
{
public void doAdd (RunData data, Context context) throws Exception
{
// put code here to add the user to the system
context.put ("username", username );
data.setMessage("User Added!");
}
public void doPerform(RunData data, Context context) throws Exception
{
data.setMessage("Button not found!");
}
}
|
然后,在我们的
HTML tag
中嵌入这样的代码:
…
<form method="post" action="$link.setAction("NewUserFoo ")">
…
<input type="submit" name="eventSubmit_doAdd" value="Add User">
…
|
这一次,请大家自己看一下执行结果吧!
原来,在我们的这个继承自
VelocityAction
的
Action
开始执行的时候,有一个“
event
”也同时传递给了它
[ii]
。
Turbine
会根据这个“
event
”自动去执行相应的方法
[iii]
。如果没有指定“
event
”或指定的“
event
”没有对应的处理方法的话,
doPerform()
方法将会被执行。
好了,看到这样的机制给我们带来了一个什么样的结果了吗?我们可以把原来需要用一个
Action
类来完成的事务写到
ActionEvent
类的一个方法里!这样,我们就不必为每一个“
Action
”都写一个对应的类,给我们日后的程序维护和文档维护带来了非常大的便利之处。尤其在一个页面中有很多
Button
的时候,我们就能更轻松的应付,并且阻止了我们陷入“
if…else if…
”的怪圈。
然而,为了获得这项神奇的能力,我们不得不以自由为代价……
J
:
1、
Action Event name
必须以“
eventSubmit_
”作为前缀
2、
完成
Action Event
的方法必须以“
do
”打头
3、
“
do
”之后的第一个字母必须大写,其余的字母必须小写
4 总结
本文整理了在
Turbine
下开发简单应用的方法步骤,主要起到一个引领入门的作用。通过本文,读者应能够快速上手,再通过一些自我实践,开发一个完整的
Turbine
应用不是难事。
Velocity template文件的查找方式
假设在
Turbine
的控制流程中,
data.getParameters().getString("template")
返回的是“
/about_us/directions/driving.vm
”的话,
Turbine
将按照如下顺序查找相应的
Screen class
:
4、
about_us.directions.Driving
5、
about_us.directions.Default
6、
about_us.Default
7、
Default
8、
VelocityScreen
(即
services.VelocityService.default.screen
)
如果返回值为
null
,则
VelocityScreen
将会被执行,此时调用的模板文件为“
templates/screens/index.vm
”。
假设出现其他任何异常,比如“
templates/screens/index.vm
”不存在,或模板文件不合法,或发生了其他任何异常,“
templates/screens/error.vm
”都将被载入执行。
此时,对于
Layout
和
Navigation
来说,将按照下面的顺序查找相应的模板文件:
1、
/about_us/directions/driving.vm
2、
/about_us/directions/default.vm
3、
/about_us/default.vm
4、
/default.vm
1、
http://www.jieesoft.com/resource/jbvelocity/jbvelocity.htm
,
用Jbuilder开发Turbine应用。
3、
http://jakarta.apache.org/turbine/tdk/tdk-howto.html
, TDK
安装指南。
4、
http://jakarta.apache.org/turbine/turbine-2.2.1/howto/context-howto.html, Velocity Context how-to。
5、
http://httpd.apache.org/docs/mod/mod_rewrite.html
,
如何用更简短的形式书写URL。