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 阅读(216) 评论(0)  编辑  收藏 所属分类: Webwork


只有注册用户登录后才能发表评论。


网站导航: