Action
簡介
Action
在
MVC
模式中擔(dān)任控制部分的角色
,
在
WebWork
中使用的最多
,
用于接收頁面參數(shù),起到對(duì)
HttpRequest
判斷處理作用。每個(gè)請(qǐng)求的動(dòng)作都對(duì)應(yīng)于一個(gè)相應(yīng)的
Action
,一個(gè)
Action
是一個(gè)獨(dú)立的工作單元和控制命令,它必需要實(shí)現(xiàn)
XWork
里的
Action
接口,實(shí)現(xiàn)
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
類里最重要的部分,它執(zhí)行返回
String
類型的值,代表在頁面執(zhí)行完后的結(jié)果,在
Action
中返回的值一般使用它上面定義的標(biāo)準(zhǔn)靜態(tài)字符常量。它有五種狀態(tài):
1
.
SUCCESS
:
Action
正確的執(zhí)行完成,返回相應(yīng)的視圖;
2
.
NONE
:表示
Action
正確的執(zhí)行完成,但并不返回任何視圖;
3
.
ERROR
:表示
Action
執(zhí)行失敗,返回到錯(cuò)誤處理視圖;
4
.
INPUT
:
Action
的執(zhí)行,需要從前端界面獲取參數(shù),
INPUT
就是代表這個(gè)參數(shù)輸入的界面,一般在應(yīng)用中,會(huì)對(duì)這些參數(shù)進(jìn)行驗(yàn)證,如果驗(yàn)證沒有通過,將自動(dòng)返回到該視圖;
5
.
LOGIN
:
Action
因?yàn)橛脩魶]有登陸的原因沒有正確執(zhí)行,將返回該登陸視圖,要求用戶進(jìn)行登陸驗(yàn)證。
下面我們將以一個(gè)用戶注冊(cè)的例子詳細(xì)介紹
Action
的原理:
功能描述:一個(gè)用戶注冊(cè)頁面
register.jsp
,用戶可以在這個(gè)頁面里輸入用戶注冊(cè)的基本信息(例如:姓名、密碼、
Email
等),輸入完成提交表單,執(zhí)行用戶注冊(cè)的
Action
,執(zhí)行成功返回成功提示的頁面(
register-result.jsp
)并將注冊(cè)的信息輸出。
流程如下:
模型:
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
是一個(gè)普通的
JavaBean
,它包含了用戶注冊(cè)的字段信息,并對(duì)每個(gè)字段提供相應(yīng)的
set
和
get
方法。下面我們來看看進(jìn)行用戶注冊(cè)動(dòng)作的
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);
//
在這里調(diào)用用戶注冊(cè)的業(yè)務(wù)邏輯,比如:將注冊(cè)信息存儲(chǔ)到數(shù)據(jù)庫
returnSUCCESS;
}
}
這個(gè)
Action
是不是特清爽?用戶注冊(cè)就這么幾行代碼搞定,當(dāng)然,我們提倡在
Action
里最好不要實(shí)現(xiàn)業(yè)務(wù)代碼,業(yè)務(wù)代碼編寫在
service.java
里面,
Action
的主要功能是提供從請(qǐng)求中取得參數(shù)的值,轉(zhuǎn)化成相應(yīng)的模型,再將模型傳遞給執(zhí)行業(yè)務(wù)操作的對(duì)象,比如:將注冊(cè)的用戶信息存儲(chǔ)到數(shù)據(jù)庫中,由業(yè)務(wù)對(duì)象執(zhí)行業(yè)務(wù)操作,再返回執(zhí)行的結(jié)果。為了簡化我們省去了注冊(cè)的業(yè)務(wù)邏輯執(zhí)行步驟
再看看我們注冊(cè)信息輸入的頁面:
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
頁面其實(shí)只是一個(gè)普通的
HTML
頁面,它提供了一個(gè)表單,用來接受用戶輸入的注冊(cè)信息,它唯一特殊的部分就是
input
輸入框定義的
name
部分,例如:用戶姓名用的是“
user. username
”。這種命名方式代表什么含義?它是必需的嗎?后面我們將會(huì)給出答案。
RegisterAction
正確執(zhí)行完成之后,會(huì)將執(zhí)行的結(jié)果返回到
register-result.jsp
頁面,由它來顯示用戶在前面頁面輸入的注冊(cè)信息。
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>
這個(gè)
Jsp
頁面使用了
WebWork
的標(biāo)簽庫
<ww:property />
,記得
HelloWorld
里的
greetings.jsp
嗎?它也使用了這個(gè)標(biāo)簽庫。我們看這個(gè):
<ww:property value="user.username"/>
它是一個(gè)普通的使用標(biāo)簽庫語句,查看這個(gè)標(biāo)簽庫的源程序,見包
com.opensymphony.webwork.views.jsp
里的
PropertyTag.java
文件,你會(huì)發(fā)現(xiàn)這個(gè)類會(huì)根據(jù)
value
后面賦予的表達(dá)式值,去
OgnlValueStack
里查找這個(gè)表達(dá)式值所對(duì)應(yīng)的操作。執(zhí)行這個(gè)語句
OgnlValueStack
會(huì)根據(jù)
value
的值(一個(gè)表達(dá)式)“
user.username
”去分別調(diào)用
RegisterAction
類的
getUser()
和
User
類的
getUsername()
方法,即:
getUser().getUsername()
,取得的數(shù)據(jù)就是前面注冊(cè)頁面輸入的用戶名。
我們把“
user.username
”這樣的語句叫做表達(dá)式語言(
Expression Language
,簡稱為
EL
)。它由
XWork
框架提供,
XWork
表達(dá)式語言的核心是
OGNL
(
Object Graph Notation Language
),
OGNL
是一種功能強(qiáng)大,技術(shù)成熟,應(yīng)用廣泛的表達(dá)式語言,將在下面的章節(jié)有詳細(xì)介紹。
我們?cè)诨氐角懊娼榻B的
register.jsp
,
Input
輸入框
<input type="text" name="user.username">
里用的“
user.username
”,現(xiàn)在我們可以明白,它不是隨意設(shè)置的,它是一個(gè)表達(dá)式語言,有著特殊的功能。看到這里,不知道你心中是否有一個(gè)疑問:我們的
RegisterAction
是如何取得用戶注冊(cè)頁面輸入的數(shù)據(jù)呢?如果你做過
Web
開發(fā),你一定會(huì)想到
RegisterAction
里必需有一些從客戶端請(qǐng)求中獲取參數(shù)的語句,例如:
類似:
String username = request.getParameter(“user. username”)
的語句(
request
是
HttpServletRequest
的對(duì)象),去從
request
請(qǐng)求里面獲取用戶輸入的參數(shù)值。可是我們這個(gè)
Action
里面只有
User
對(duì)象簡單的
get
方法,并沒有其它的代碼。
Xwork
框架的
Action
是如何去實(shí)現(xiàn)了與
Web
無關(guān)?
request
請(qǐng)求的參數(shù)是怎么傳遞到我們
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>
看了前面的介紹,這段配置文件應(yīng)該不難理解。用戶通過注冊(cè)頁面
register.jsp
輸入自己的注冊(cè)信息,提交表單到動(dòng)作
register.action
,它將有
ServletDispatcher
調(diào)度,從配置文件
xwork.xml
里查找與“
register
”匹配的
Action
名字,即上面配置的
Action
。通過這個(gè)名字
XWork
框架找到這個(gè)
Action
的類:
example.register.RegisterAction
,
XWork
框架會(huì)負(fù)責(zé)去創(chuàng)建這個(gè)
Action
類的對(duì)象并調(diào)用
execute()
方法進(jìn)行用戶注冊(cè)操作。正確執(zhí)行
execute()
方法返回
String
類型數(shù)據(jù)“
success
”之后,它會(huì)請(qǐng)求再派遣到
register-result.jsp
頁面。
在這段配置文件里,你一定注意到了它特殊的一句:
<interceptor-ref name="params"/>
,
interceptor-ref
標(biāo)簽設(shè)置這個(gè)
Action
用到的攔截器
(Interceptor)
,“
params
”引用的是配置文件中的
<interceptor name="params" class="
com.opensymphony.xwork.interceptor.ParametersInterceptor"/>
,這個(gè)攔截器將在
RegisterAction
的
execute()
方法執(zhí)行之前調(diào)用,作用是將
request
請(qǐng)求的參數(shù)值通過表達(dá)式語言設(shè)置到相應(yīng)
RegisterAction
的模型里。例如:
register.jsp
里的
<input type="text" name="user.username">
,它輸入的值會(huì)由
RegisterAction
類的
getUser()
和
User
類的
setUserName(“…”)
設(shè)置到這個(gè)
User
模型里。假設(shè)你在注冊(cè)頁面輸入用戶名“
babydavic
”,提交表單
ParametersInterceptor
就會(huì)下面的操作:首先從請(qǐng)求中取得參數(shù)的名字和名字對(duì)應(yīng)的值,分別為:“
user.username
”和“
babydavic
”,根據(jù)這個(gè)名字,從
OgnlValueStack
中取得堆棧最上面的
getUser().setUsername(“babydavic”)
操作,即取得
RegisterAction
對(duì)象的
User
模型,并設(shè)置
username
屬性的值為“
babydavic
”。
原來,我們的
Action
是通過
XWork
的攔截器
ParametersInterceptor
從提交的表單中取得請(qǐng)求的參數(shù)和值,再通過
OgnlValueStack
來執(zhí)行表達(dá)式,調(diào)用
Action
和模型里相應(yīng)的
ge
或
set
方法,將從請(qǐng)求中取得的值設(shè)置到模型中去。
register.jsp
中
Input
輸入框的
name="user.username"
是必需要遵守
OGNL
的命名規(guī)則。也正是很多攔截器的使用,使得我們的
Action
類和
Web
實(shí)現(xiàn)了完全的解耦,讓我們的
Action
能如此的簡單、優(yōu)雅,攔截器的原理后面章節(jié)我們也將會(huì)有詳細(xì)的介紹。
Action
根據(jù)
FormBean
的不同可以分為二類,
一類是
Field-Driven
(字段驅(qū)動(dòng)的)
Action
Action
將直接用自己的字段來充當(dāng)
FormBean
的功能,我們的例子就是使用這種方式。它一般用在頁面表單比較簡單的情況使用,而且可以直接用域?qū)ο笞鳛?/span>
Action
的字段,這樣就不用在另寫
FormBean
,減少了重復(fù)代碼。
另一類是
Model-Driven
(模型驅(qū)動(dòng)的)
Action
它很像
Struts
的
FormBean
,但在
WebWork
中,只要普通
Java
對(duì)象就可以充當(dāng)模型部分。
Model-Driven
(模型驅(qū)動(dòng)的)
Action
要求我們的
Action
實(shí)現(xiàn)
com.opensymphony.xwork. ModelDriven
接口,它有一個(gè)方法:
Object getModel();
,我們用這個(gè)方法返回我們的模型對(duì)象就可以了。
我們可以將前面的
RegisterAction.java
改為
Model-Driven
(模型驅(qū)動(dòng)的)
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);
//
在這里調(diào)用用戶注冊(cè)的業(yè)務(wù)邏輯,比如:將注冊(cè)信息存儲(chǔ)到數(shù)據(jù)庫
returnSUCCESS;
}
public Object getModel() {
return user;
}
}
這時(shí)我們輸入信息的頁面也有了變化:
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>
我們發(fā)現(xiàn),輸入框里的命名發(fā)生了變化。它們都少了“
user.
”這部分信息。
當(dāng)我們采用
Model-Driven
(模型驅(qū)動(dòng)的)
Action
時(shí),它將取得模型對(duì)象保存在值堆棧中。“
name="username"
”就是代表直接調(diào)用模型對(duì)象的
setUsername()
方法。
我們
Action
的在配置文件中,也要給它指定一個(gè)攔截器
model-driven
,
它的作用就是將模型對(duì)象保存到值堆棧中。關(guān)于攔截器的介紹請(qǐng)看下面的章節(jié)。
配置文件如下:
<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
周銳 閱讀(648)
評(píng)論(0) 編輯 收藏 所屬分類:
Webwork