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
				)并将注册的信息输出。
		
		
				流程如下:
		
		
				
						
						
						
						
						
						
						
						
				
		
		
				模型:
				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
				能如此的简单、优雅,拦截器的原理后面章节我们也将会有详细的介绍。
		
		 
		
		
				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-12-13 17:28 
周锐 阅读(667) 
评论(0)  编辑  收藏  所属分类: 
Webwork