HelloWorld
首先看下面這個程序HelloWorldAction.java:
CODE:
package helloWorld
import com.opensymphony.xwork.Action;
public class HelloWorldAction implements Action{
String greeting;
public String getGreeting() {
return greeting;
}
public String execute() throws Exception {
greeting = "Hello World!";
return SUCCESS;
}
}
[Copy to clipboard]
HelloWorldAction是一個普通的Java類,它實現了Action這個接口。Action是一個非常簡單的接口,只有一個方法:public String execute() throws Exception; ,Action類介紹見下一節。HelloWorldAction有一個String類型字段greeting,在execute()方法中,greeting被賦值“Hello World!”,並返回String型常量SUCCESS,SUCCESS的定義詳見Action接口,這個常量代表了execute()方法執行成功,將返回成功頁面。
返回的頁面greetings.jsp代碼如下:
CODE:
<%@ taglib prefix="ww" uri="webwork" %>
<html>
<head>
<title>First WebWork Example</title>
</head>
<body>
<p><ww:property value="greeting"/></p>
</body>
</html>
[Copy to clipboard]
greetings.jsp很簡單的jsp頁面,它使用了WebWork自帶的標籤庫。它的作用是輸出變量“greeting”的值。這個<ww:property value="greeting"/>語句,相當於調用相應Action(HelloWorldAction)的getGreeting()方法,取得變量“greeting”的值。
我們的HelloWorld代碼就這麼多,完了。可是,HelloWorldAction怎麼去調用、執行?執行成功它又怎麼知道返回到greetings.jsp?XWork的配置文件xwork.xml會負責將要執行的Action和展現的視圖連接起來,見xwork.xml的如下片斷:
CODE:
<action name="hello" class=" helloWorld .HelloWorldAction">
<result name="success" type="dispatcher">
<param name="location">/greetings.jsp</param>
</result>
</action>
[Copy to clipboard]
我們先看action標籤:name=”hello”,表示我們調用這個Action的標識是hello,這樣我們可以通過下面的url訪問這個Action:…/hello.action,
例如:http://localhost:8080/webwork/hello.action;class=" helloWorld .HelloWorldAction"很好理解,這是真正調用執行的類。我們在看看result標籤:name="success",記得前面HelloWorldAction返回的字符常量SUCCESS嗎?它的值其實就是“success”,它表示Action執行成功返回success就轉向這個結果;type="dispatcher"表示執行完Action,轉向結果頁面的方式;param參數指定了結果頁面的位置:/greetings.jsp。
代碼寫完,剩下的當然是編譯、部署。啓動tomcat服務器之後我們就可以執行了:
在瀏覽器裏輸入你的地址:http://localhost:8080/webwork/hello.action
你將會看到如下結果:
Action(動作)
Action介紹
Action在MVC模式中擔任控制部分的角色,在WebWork中使用的最多。每個請求的動作都對應於一個相應的Action,一個Action是一個獨立的工作單元和控制命令,它必需要實現XWork裏的Action接口,實現Action接口的execute()方法。Action接口的代碼如下:
CODE:
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;
}
[Copy to clipboard]
excute()方法是Action類裏最重要的部分,它執行返回String類型的值,在Action中返回的值一般使用它上面定義的標準靜態字符常量。例如:前面的HelloWorldAction返回的就是SUCCESS字符常量,真正的值當然就是“success”,它與xwork配置文件裏result標籤name的值是相對應的。它用來決定execute()方法執行完成之後,調用哪一種返回結果。字符常量的含義如下:
SUCCESS:Action正確的執行完成,返回相應的視圖;
NONE:表示Action正確的執行完成,但並不返回任何視圖;
ERROR:表示Action執行失敗,返回到錯誤處理視圖;
INPUT:Action的執行,需要從前端界面獲取參數,INPUT就是代表這個參數輸入的界面,一般在應用中,會對這些參數進行驗證,如果驗證沒有通過,將自動返回到該視圖;
LOGIN:Action因爲用戶沒有登陸的原因沒有正確執行,將返回該登陸視圖,要求用戶進行登陸驗證。
用戶註冊例子
下面我們將以一個用戶註冊的例子詳細介紹Action的原理:
功能描述:一個用戶註冊頁面register.jsp,用戶可以在這個頁面裏輸入用戶註冊的基本信息(例如:姓名、密碼、Email等),輸入完成提交表單,執行用戶註冊的Action,執行成功返回成功提示的頁面(register-result.jsp)並將註冊的信息輸出。
模型:User.java
控制:RegisterAction.java
視圖:register.jsp、register-result.jsp
配置:xwork.xml
User.java:
CODE:
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;
}
}
[Copy to clipboard]
模型User是一個普通的JavaBean,它包含了用戶註冊的字段信息,並對每個字段提供相應的set和get方法。下面我們來看看進行用戶註冊動作的RegisterAction.java:
CODE:
package example.register;
import com.opensymphony.xwork.Action;
/**
* @author moxie-qac
*/
public class RegisterAction implements Action {
private User user= new User();
public User getUser() {
return this.user;
}
public String execute() {
System.out.println("Start execute 。。。。。。。。。。。。。");
System.out.println("User="+user);
//在這裏調用用戶註冊的業務邏輯,比如:將註冊信息存儲到數據庫
return SUCCESS;
}
}
[Copy to clipboard]
這個Action是不是特清爽?用戶註冊就這麼幾行代碼搞定,當然,我們提倡在Action裏最好不要實現業務代碼,Action的主要功能是提供從請求中取得參數的值,轉化成相應的模型,再將模型傳遞給執行業務操作的對象,比如:將註冊的用戶信息存儲到數據庫中,由業務對象執行業務操作,再返回執行的結果。爲了簡化我們省去了註冊的業務邏輯執行步驟。
再看看我們註冊信息輸入的頁面:register.jsp
CODE:
<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>
[Copy to clipboard]
register.jsp頁面其實只是一個普通的HTML頁面,它提供了一個表單,用來接受用戶輸入的註冊信息,它唯一特殊的部分就是input輸入框定義的name部分,例如:用戶姓名用的是“user. username”。這種命名方式代表什麼含義?它是必需的嗎?後面我們將會給出答案。
RegisterAction正確執行完成之後,會將執行的結果返回到register-result.jsp頁面,由它來顯示用戶在前面頁面輸入的註冊信息。register-result.jsp代碼如下:
CODE:
<%@ 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>
</html>
[Copy to clipboard]
這個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:
CODE:
<action name="register" class="example.register.RegisterAction" >
<result name="success" type="dispatcher">
<param name="location">/register-result.jsp</param>
</result>
<interceptor-ref name="params"/>
</action>
[Copy to clipboard]
看了前面的介紹,這段配置文件應該不難理解。用戶通過註冊頁面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模型裏。假設你在註冊頁面輸入用戶名“moxie”,提交表單ParametersInterceptor就會下面的操作:首先從請求中取得參數的名字和名字對應的值,分別爲:“user.username”和“moxie”,根據這個名字,從OgnlValueStack中取得堆棧最上面的getUser().setUsername(“moxie”)操作,即取得RegisterAction對象的User模型,並設置username屬性的值爲“moxie”。
原來,我們的Action是通過XWork的攔截器ParametersInterceptor從提交的表單中取得請求的參數和值,再通過OgnlValueStack來執行表達式,調用Action和模型裏相應的ge或set方法,將從請求中取得的值設置到模型中去。register.jsp中Input輸入框的name="user.username"是必需要遵守OGNL的命名規則。也正是很多攔截器的使用,使得我們的Action類和Web實現了完全的解耦,讓我們的Action能如此的簡單、優雅,攔截器的原理後面章節我們也將會有詳細的介紹。
羅索了這麼多,你一定是精通了這個用戶註冊的例子了吧!呵呵!