Turbine实战(下) menlion(原作)

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应用。
5、  http://httpd.apache.org/docs/mod/mod_rewrite.html , 如何用更简短的形式书写URL。


[i] 在Turbine2.2的示例程序中,使用VelocityECSLayout作为缺省的Layout类,但这个类不支持Frame。除此之外,还提供了VelocityDirectLayout、VelocityXslLayout两个类供开发者使用。
[ii] 在这里,这个“Event”就是“eventSubmit_doAdd”。
[iii] 此时,Turbine使用java.lang.reflect包完成了这件神奇的事。不过值得注意的是:java.lang.reflect包可是一个“大名”昭著的性能杀手。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值