Vincent

Vicent's blog
随笔 - 74, 文章 - 0, 评论 - 5, 引用 - 0
数据加载中……

WebWork介绍-Action篇

Action 简介
Action 在 MVC 模式中担任控制部分的角色 , 在 WebWork 中使用的最多 , 用于接收页面参数,起到对 HttpRequest 判断处理作用。每个请求的动作都对应于一个相应的 Action ,一个 Action 是一个独立的工作单元和控制命令,它必需要实现 XWork 里的 Action 接口,实现 Action 接口的 execute() 方法。 Action 接口的代码如下:
 
package com.opensymphony.xwork;
 
import java.io.Serializable;
 
public interface Action extends Serializable {
   
    public static final String SUCCESS = "success";
    public static final String NONE = "none";
    public static final String ERROR = "error";
    public static final String INPUT = "input";
    public static final String LOGIN = "login";
   
    public String execute() throws Exception;
}
excute() 方法是 Action 类里最重要的部分,它执行返回 String 类型的值,代表在页面执行完后的结果,在 Action 中返回的值一般使用它上面定义的标准静态字符常量。它有五种状态:
 
1 . SUCCESS : Action 正确的执行完成,返回相应的视图;
2 . NONE :表示 Action 正确的执行完成,但并不返回任何视图;
3 . ERROR :表示 Action 执行失败,返回到错误处理视图;
4 . INPUT : Action 的执行,需要从前端界面获取参数, INPUT 就是代表这个参数输入的界面,一般在应用中,会对这些参数进行验证,如果验证没有通过,将自动返回到该视图;
5 . LOGIN : Action 因为用户没有登陆的原因没有正确执行,将返回该登陆视图,要求用户进行登陆验证。
 
下面我们将以一个用户注册的例子详细介绍 Action 的原理:
功能描述:一个用户注册页面 register.jsp ,用户可以在这个页面里输入用户注册的基本信息(例如:姓名、密码、 Email 等),输入完成提交表单,执行用户注册的 Action ,执行成功返回成功提示的页面( register-result.jsp )并将注册的信息输出。
流程如下:

Register.jsp
Action
校验
登录
Service
业务处理
DAO
数据处理

模型: User.java                      
控制: RegisterAction.java
视图: register.jsp 、 register-result.jsp
配置: xwork.xml
 
User.java :
 
package register;
 
public class User {
    private String username;
    private String password;
    private String email;
    private int age;
 
    public String getUsername() {
        return username;
    }
 
    public void setUsername(String username) {
        this.username = username;
    }
……
   
    public int getAge() {
        return age;
    }
 
    public int setAge(int age) {
        this.age = age;
    }
   
    public String toString(){
    return "username=" + username
         + ";password=" + password
         + ";email=" + email
         + ";age=" + age;
    }
}
 
 
模型 User 是一个普通的 JavaBean ,它包含了用户注册的字段信息,并对每个字段提供相应的 set 和 get 方法。下面我们来看看进行用户注册动作的 RegisterAction.java :
package example.register;
 
import com.opensymphony.xwork.Action;
 
/**
 *@authorbabydavic-qac
 *         achqian@yahoo.com.cn
 */
public class RegisterAction implements Action {
   
    privateUseruser=newUser();
 
    public User getUser(){
        returnthis.user;
    }
   
    publicStringexecute(){
       
        System.out.println("Start execute 。。。。。。。。。。。。。 " );
        System.out.println("User="+user);
        // 在这里调用用户注册的业务逻辑,比如:将注册信息存储到数据库
   
        returnSUCCESS;
    }
}
 
这个 Action 是不是特清爽?用户注册就这么几行代码搞定,当然,我们提倡在 Action 里最好不要实现业务代码,业务代码编写在 service.java 里面, Action 的主要功能是提供从请求中取得参数的值,转化成相应的模型,再将模型传递给执行业务操作的对象,比如:将注册的用户信息存储到数据库中,由业务对象执行业务操作,再返回执行的结果。为了简化我们省去了注册的业务逻辑执行步骤
 
再看看我们注册信息输入的页面: register.jsp
<html>
<head><title>Register Example</title></head>
<body>
<table border=0 width=97%>
<tr><td align="left">
    <form name="register" action="register.action" method="post">
        Username:<input type="text" name="user.username"><br>
        Password:<input type="text" name="user.password"><br>
        Email:<input type="text" name="user.email"><br>
        Age:<input type="text" name="user.age"><br>
        <input type="submit" name="Submit"><br>
    </form>
</td></tr>
</table>
</body>
</html>
 
 
register.jsp 页面其实只是一个普通的 HTML 页面,它提供了一个表单,用来接受用户输入的注册信息,它唯一特殊的部分就是 input 输入框定义的 name 部分,例如:用户姓名用的是“ user. username ”。这种命名方式代表什么含义?它是必需的吗?后面我们将会给出答案。
RegisterAction 正确执行完成之后,会将执行的结果返回到 register-result.jsp 页面,由它来显示用户在前面页面输入的注册信息。 register-result.jsp 代码如下 :
<%@ taglib prefix="ww" uri="webwork" %>
<html>
<head><title>Register result</title></head>
<body>
    <table border=0 width=97%>
        <tr>
            <td align="left">
            Congratulation,your register success!<p>
            Username:<ww:property value="user.username"/><br>
            Password:<ww:property value="user.password"/><br>
            Email:<ww:property value="user.email"/><br>
            Age:<ww:property value="user.age"/><br>
            </td>
        </tr>
    </table>
</body>
 
这个 Jsp 页面使用了 WebWork 的标签库 <ww:property /> ,记得 HelloWorld 里的 greetings.jsp 吗?它也使用了这个标签库。我们看这个: <ww:property value="user.username"/>
它是一个普通的使用标签库语句,查看这个标签库的源程序,见包
com.opensymphony.webwork.views.jsp
里的 PropertyTag.java 文件,你会发现这个类会根据 value 后面赋予的表达式值,去 OgnlValueStack 里查找这个表达式值所对应的操作。执行这个语句 OgnlValueStack 会根据 value 的值(一个表达式)“ user.username ”去分别调用 RegisterAction 类的 getUser() 和 User 类的 getUsername() 方法,即: getUser().getUsername() ,取得的数据就是前面注册页面输入的用户名。
我们把“ user.username ”这样的语句叫做表达式语言( Expression Language ,简称为 EL )。它由 XWork 框架提供, XWork 表达式语言的核心是 OGNL ( Object Graph Notation Language ), OGNL 是一种功能强大,技术成熟,应用广泛的表达式语言,将在下面的章节有详细介绍。
 
我们在回到前面介绍的 register.jsp , Input 输入框
<input type="text" name="user.username">
里用的“ user.username ”,现在我们可以明白,它不是随意设置的,它是一个表达式语言,有着特殊的功能。看到这里,不知道你心中是否有一个疑问:我们的 RegisterAction 是如何取得用户注册页面输入的数据呢?如果你做过 Web 开发,你一定会想到 RegisterAction 里必需有一些从客户端请求中获取参数的语句,例如: 类似: String username = request.getParameter(“user. username”) 的语句( request 是 HttpServletRequest 的对象),去从 request 请求里面获取用户输入的参数值。可是我们这个 Action 里面只有 User 对象简单的 get 方法,并没有其它的代码。 Xwork 框架的 Action 是如何去实现了与 Web 无关? request 请求的参数是怎么传递到我们 Action 的模型 User 中呢?
 
在回答答案之前,我们先看一看 Xwork 的配置文件 xwork.xml :
<action name= "register" class= "example.register.RegisterAction" >
        <resultname="success"type="dispatcher">
            <paramname="location">/register-result.jsp</param>
        </result>
        <interceptor-refname="params"/>
</action>
 
看了前面的介绍,这段配置文件应该不难理解。用户通过注册页面 register.jsp 输入自己的注册信息,提交表单到动作 register.action ,它将有 ServletDispatcher 调度,从配置文件 xwork.xml 里查找与“ register ”匹配的 Action 名字,即上面配置的 Action 。通过这个名字 XWork 框架找到这个 Action 的类: example.register.RegisterAction , XWork 框架会负责去创建这个 Action 类的对象并调用 execute() 方法进行用户注册操作。正确执行 execute() 方法返回 String 类型数据“ success ”之后,它会请求再派遣到 register-result.jsp 页面。
在这段配置文件里,你一定注意到了它特殊的一句: <interceptor-ref name="params"/> , interceptor-ref 标签设置这个 Action 用到的拦截器 (Interceptor) ,“ params ”引用的是配置文件中的 <interceptor name="params" class="
com.opensymphony.xwork.interceptor.ParametersInterceptor"/>
,这个拦截器将在 RegisterAction 的 execute() 方法执行之前调用,作用是将 request 请求的参数值通过表达式语言设置到相应 RegisterAction 的模型里。例如: register.jsp 里的 <input type="text" name="user.username"> ,它输入的值会由 RegisterAction 类的 getUser() 和 User 类的 setUserName(“…”) 设置到这个 User 模型里。假设你在注册页面输入用户名“ babydavic ”,提交表单 ParametersInterceptor 就会下面的操作:首先从请求中取得参数的名字和名字对应的值,分别为:“ user.username ”和“ babydavic ”,根据这个名字,从 OgnlValueStack 中取得堆栈最上面的 getUser().setUsername(“babydavic”) 操作,即取得 RegisterAction 对象的 User 模型,并设置 username 属性的值为“ babydavic ”。
原来,我们的 Action 是通过 XWork 的拦截器 ParametersInterceptor 从提交的表单中取得请求的参数和值,再通过 OgnlValueStack 来执行表达式,调用 Action 和模型里相应的 ge 或 set 方法,将从请求中取得的值设置到模型中去。 register.jsp 中 Input 输入框的 name="user.username" 是必需要遵守 OGNL 的命名规则。也正是很多拦截器的使用,使得我们的 Action 类和 Web 实现了完全的解耦,让我们的 Action 能如此的简单、优雅,拦截器的原理后面章节我们也将会有详细的介绍。
 
Field-Driven Action vs. Model-Driven Action (红色代码部分就代表两种类型的不同之处)
Action 根据 FormBean 的不同可以分为二类,
一类是 Field-Driven (字段驱动的) Action
   Action 将直接用自己的字段来充当 FormBean 的功能,我们的例子就是使用这种方式。它一般用在页面表单比较简单的情况使用,而且可以直接用域对象作为 Action 的字段,这样就不用在另写 FormBean ,减少了重复代码。
另一类是 Model-Driven (模型驱动的) Action
它很像 Struts 的 FormBean ,但在 WebWork 中,只要普通 Java 对象就可以充当模型部分。 Model-Driven (模型驱动的) Action 要求我们的 Action 实现 com.opensymphony.xwork. ModelDriven 接口,它有一个方法: Object getModel(); ,我们用这个方法返回我们的模型对象就可以了。
我们可以将前面的 RegisterAction.java 改为 Model-Driven (模型驱动的) Action :
package example.register;
 
import com.opensymphony.xwork.Action;
import com.opensymphony.xwork.ModelDriven;
 
/**
 *@authormoxie-qac
 *         achqian@yahoo.com.cn
 *
 */
public class RegisterActionModel implements Action,ModelDriven{
    privateUseruser=newUser();
   
    publicStringexecute()throwsException{
        System.out.println("Start execute...... 。。。。。。。。。。。。。。 " );
        System.out.println("User="+user);
        // 在这里调用用户注册的业务逻辑,比如:将注册信息存储到数据库
   
        returnSUCCESS;
    }
   
    public Object getModel() {
        return user;
    }
}
这时我们输入信息的页面也有了变化: register-model.jsp
<html>
<head><title>Register Example</title></head>
<body>
<table border=0 width=97%>
<tr><td align="left">
    <form name="register" action="registerModel.action" method="post">
        Username:<input type="text" name="username"><br>
        Password:<input type="text" name="password"><br>
        Email:<input type="text" name="email"><br>
        Age:<input type="text" name="age"><br>
        <input type="submit" name="Submit"><br>
    </form>
</td></tr>
</table>
</body>
</html>
我们发现,输入框里的命名发生了变化。它们都少了“ user. ”这部分信息。
当我们采用 Model-Driven (模型驱动的) Action 时,它将取得模型对象保存在值堆栈中。“ name="username" ”就是代表直接调用模型对象的 setUsername() 方法。
我们 Action 的在配置文件中,也要给它指定一个拦截器 model-driven , 它的作用就是将模型对象保存到值堆栈中。关于拦截器的介绍请看下面的章节。
配置文件如下:
<action name= "registerModel" class= "example.register.RegisterActionModel" >
        <resultname="success"type="dispatcher">
            <paramname="location">/register-result-model.jsp</param>
        </result>
        <interceptor-ref name="model-driven"/>
        <interceptor-refname="params"/>
    </action>

posted on 2006-09-01 13:38 Binary 阅读(271) 评论(0)  编辑  收藏 所属分类: Webwork