Action介绍
Action在MVC模式中担任控制部分的角色,在WebWork中使用的最多。每个请求的动作都对应于一个相应的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中返回的值一般使用它上面定义的标准静态字符常量。例如:前面的HelloWorldAction返回的就是SUCCESS字符常量,真正的值当然就是“success”,它与xwork配置文件里result标签name的值是相对应的。它用来决定execute()方法执行完成之后,调用哪一种返回结果。字符常量的含义如下:
SUCCESS:Action正确的执行完成,返回相应的视图;
NONE:表示Action正确的执行完成,但并不返回任何视图;
ERROR:表示Action执行失败,返回到错误处理视图;
INPUT:Action的执行,需要从前端界面获取参数,INPUT就是代表这个参数输入的界面,一般在应用中,会对这些参数进行验证,如果验证没有通过,将自动返回到该视图;
LOGIN:Action因为用户没有登陆的原因没有正确执行,将返回该登陆视图,要求用户进行登陆验证。
用户注册例子:
功能描述:一个用户注册页面register.jsp,用户可以在这个页面里输入用户注册的基本信息(例如:用户名、姓名、年龄、生日、密码等),输入完成提交表单,执行用户注册的Action,执行成功返回成功提示的页面(register-result.jsp)并将注册的信息输出。
模型:User.java
控制:RegisterAction.java
视图:register.jsp、register-result.jsp
配置:xwork.xml
User.java:
package com.zh2;
public class User {
private String ID;
private String name;
private int age;
private String birthday;
private String pw;
public void setID(String iD) {
ID = iD;
}
public String getID() {
return ID;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getBirthday() {
return birthday;
}
public void setPw(String pw) {
this.pw = pw;
}
public String getPw() {
return pw;
}
public String toString() {
return "用户名=" + this.ID + "; 姓名=" + this.name + "; 年龄=" + this.age
+ ";生日=" + this.birthday + "; 密码=" + this.pw;
}
}
模型User是一个普通的JavaBean,它包含了用户注册的字段信息,并对每个字段提供相应的set和get方法。下面我们来看看进行用户注册动作的RegisterAction.java:
package com.zh2;
import com.opensymphony.xwork.Action;
public class RegisterAction implements Action{
private User user= new User();
public User getUser() {
return this.user;
}
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println("The user:" + user);
return SUCCESS;
}
}
我们提倡在Action里最好不要实现业务代码,Action的主要功能是提供从请求中取得参数的值,转化成相应的模型,再将模型传递给执行业务操作的对象,比如:将注册的用户信息存储到数据库中,由业务对象执行业务操作,再返回执行的结果。为了简化我们省去了注册的业务逻辑执行步骤。
再看看我们注册信息输入的页面:register.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>RegisterTable</title>
</head>
<body>
<form name="register" action="register.action" method="post">
<!-- οnsubmit="return checkForm(this)-->
<table width="80%" border="1" align="center" cellpadding="2"
cellspacing="0">
<caption><font color="red" style="font-size: 30px">Register</font><br>
</caption>
<tr bgcolor="#EFEFEF">
<td width="25%" align="right">UserID:</td>
<td width="30%" valign="bottom"><input name="user.ID" type="text"
id="uid" size="20" maxlength="50"></td>
</tr>
<tr>
<td width="25%" align="right">UserName:</td>
<td width="30%" valign="bottom"><input name="user.name" type="text"
id="name" size="20" maxlength="50"></td>
</tr>
<tr bgcolor="#EFEFEF">
<td align="right">UserAge:</td>
<td><input name="user.age" type="text" id="age" size="20"
maxlength="50"></td>
</tr>
<tr>
<td width="25%" align="right">UserBirthday:</td>
<td width="30%" valign="bottom"><input name="user.birthday"
type="text" id="birthday" size="20" maxlength="50"></td>
</tr>
<tr bgcolor="#EFEFEF">
<td align="right">UserPw:</td>
<td><input name="user.pw" type="password" id="pw" size="20"
maxlength="50"></td>
</tr>
<tr>
<td align="right"><input name="submit" type="submit" value="submit"></td>
<td><input name="reset" type="reset" value="reset"></td>
</tr>
</table>
</form>
</body>
</html>
register.jsp页面其实只是一个普通的HTML页面,它提供了一个表单,用来接受用户输入的注册信息,它唯一特殊的部分就是input输入框定义的name部分,例如:用户姓名用的是“user. name”。这种命名方式代表什么含义?它是必需的吗?后面我们将会给出答案。
RegisterAction正确执行完成之后,会将执行的结果返回到register-result.jsp页面,由它来显示用户在前面页面输入的注册信息。register-result.jsp代码如下:
<%@ taglib prefix="ww" uri="webwork" contentType="text/html; charset=utf-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>RegisterSuccess</title>
</head>
<body>
<table width="80%" border="1" align="center" cellpadding="2"
cellspacing="0">
<caption><font color="red" style="font-size: 30px">Congratulation,your register success!</font><br>
</caption>
<tr bgcolor="#EFEFEF">
<td width="25%" align="right">UserID:</td>
<td width="30%" valign="bottom"><ww:property value="user.ID"/></td>
</tr>
<tr>
<td width="25%" align="right">UserName:</td>
<td width="30%" valign="bottom"><ww:property value="user.name"/></td>
</tr>
<tr bgcolor="#EFEFEF">
<td align="right">UserAge:</td>
<td><ww:property value="user.age"/></td>
</tr>
<tr>
<td width="25%" align="right">UserBirthday:</td>
<td width="30%" valign="bottom"><ww:property value="user.birthday"/></td>
</tr>
<tr bgcolor="#EFEFEF">
<td align="right">UserPw:</td>
<td><ww:property value="user.pw"/></td>
</tr>
</table>
</body>
</html>
这个Jsp页面使用了WebWork的标签库 <ww:property />。我们看这个:<ww:property value="user.name"/>
它是一个普通的使用标签库语句,查看这个标签库的源程序,见包
com.opensymphony.webwork.views.jsp里的PropertyTag.java文件,你会发现这个类会根据value后面赋予的表达式值,去OgnlValueStack里查找这个表达式值所对应的操作。执行这个语句OgnlValueStack会根据value的值(一个表达式)“user.name”去分别调用RegisterAction类的getUser()和User类的getName()方法,即:getUser().getName(),取得的数据就是前面注册页面输入的用户名。
我们把“user.name”这样的语句叫做表达式语言(Expression Language,简称为EL)。它由XWork框架提供,XWork表达式语言的核心是OGNL(Object Graph Notation Language),OGNL是一种功能强大,技术成熟,应用广泛的表达式语言,将在下面的章节有详细介绍。
我们在回到前面介绍的register.jsp,Input输入框
<input type="text" name="user.name">里用的“user.name”,现在我们可以明白,它不是随意设置的,它是一个表达式语言,有着特殊的功能。看到这里,不知道你心中是否有一个疑问:我们的RegisterAction是如何取得用户注册页面输入的数据呢?如果你做过Web开发,你一定会想到RegisterAction里必需有一些从客户端请求中获取参数的语句,例如:类似:String username = request.getParameter(“user. name”)的语句(request是HttpServletRequest的对象),去从request请求里面获取用户输入的参数值。可是我们这个Action里面只有User对象简单的get方法,并没有其它的代码。Xwork框架的Action是如何去实现了与Web无关?request请求的参数是怎么传递到我们Action的模型User中呢?
在回答答案之前,我们先看一看Xwork的配置文件xwork.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
<xwork>
<include file="webwork-default.xml"/>
<package name="default" extends="webwork-default">
<action name="register" class="com.zh2.RegisterAction" >
<result name="success" type="dispatcher">
<param name="location">/register-result.jsp</param>
</result>
<interceptor-ref name="params"/>
</action>
</package>
</xwork>
看了前面的介绍,这段配置文件应该不难理解。用户通过注册页面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.name">,它输入的值会由RegisterAction类的getUser()和User类的setName(“…”)设置到这个User模型里。假设你在注册页面输入用户名“moxie”,提交表单ParametersInterceptor就会下面的操作:首先从请求中取得参数的名字和名字对应的值,分别为:“user.name”和“moxie”,根据这个名字,从OgnlValueStack中取得堆栈最上面的getUser().setName(“moxie”)操作,即取得RegisterAction对象的User模型,并设置name属性的值为“moxie”。
原来,我们的Action是通过XWork的拦截器ParametersInterceptor从提交的表单中取得请求的参数和值,再通过OgnlValueStack来执行表达式,调用Action和模型里相应的ge或set方法,将从请求中取得的值设置到模型中去。register.jsp中Input输入框的name="user.name"是必需要遵守OGNL的命名规则。也正是很多拦截器的使用,使得我们的Action类和Web实现了完全的解耦,让我们的Action能如此的简单、优雅。
关于webWork的更多了解,可访问http://blog.chinaunix.net/uid-20452426-id-1676205.html