package 節(jié)點
<package name="user" namespace="/user" extends="struts-default" abstract="false">
</package>
屬性名稱
|
是否必須
|
屬性描述
|
name
|
是
|
指定 package 的名字,這個名字在工程內(nèi)必須是唯一的
|
extends
|
是
|
指明要擴展的包的名字。如 extends="struts-default"
|
abstract
|
否
|
指明 package 是否是抽象的。默認是 false。
抽象的 package 不能擁有任何的 action,只能作為父包被繼承
|
namespace
|
否
|
命名空間。默認值是 ""。
若指定了該屬性的值,那么,訪問該 package 下的所有 Action 都需要帶上這個命名空間
|
action 節(jié)點
<action name="domain" class="fan.tutorial.action.DomainAction" method="launch">
<result>/domain.jsp</result>
</action>
屬性名稱
|
是否必須
|
屬性描述
|
name
|
是
|
指定 Action 的名字
|
class
|
否
|
指定 Action 的完整類路徑。
默認是 class = "com.opensymphony.xwork2.ActionSupport"
|
method
|
否
|
指定 Action 執(zhí)行時調(diào)用的方法。默認是 method = "execute"
|
result 節(jié)點
<result name="success" type="dispatcher">/success.jsp</result>
屬性名稱
|
是否必須
|
屬性描述
|
name
|
否
|
指定視圖結(jié)果的名稱,用于根據(jù)不同的邏輯名稱匹配不同的視圖結(jié)果頁面。
默認值 name = "success"
|
type
|
否
|
指定視圖結(jié)果類型,用于根據(jù)不同的類型 ( 例如轉(zhuǎn)發(fā)或重定向等 ) 跳轉(zhuǎn)到指定的視圖頁面
默認值 type = "dispatcher"
|
result 節(jié)點的結(jié)果類型
結(jié)果類型名稱
|
結(jié)果類型描述
|
chain
|
用于將多個 Action 鏈接起來執(zhí)行,來共同完成一次請求 ( 數(shù)據(jù)可以在多個 Action 中共享 )
|
dispatcher
|
轉(zhuǎn)發(fā)。這是默認的結(jié)果類型。
本質(zhì)是通過 Servlet API 的 RequestDispatcher.forward() 來完成
|
redirect
|
重定向。
本質(zhì)是通過 Servlet API 的 HttpServletResponse.sendRedirect() 來完成。
重定向是服務器向客戶端瀏覽器發(fā)回302狀態(tài)碼以及重定向地址 Location,瀏覽器接收后將重新發(fā)起一次新的 HTTP 請求。前一次 HTTP 請求所包含的數(shù)據(jù)是不能被后一次 HTTP 請求所共享的。
|
redirectAction
|
與 redirect 結(jié)果類型相似,只是它專門用來映射到另外的一個 Action 動作
|
stream
|
向客戶端瀏覽器發(fā)送 InputStream 流對象,通常可以用來作為文件下載的一種手段
|
配置全局結(jié)果
<package name="basic" extends="struts-default">
<global-results>
<result name="error">/pages/global/error.jsp</result>
<result name="success">/pages/global/success.jsp</result>
</global-results>
</package>
全局結(jié)果是在 package 中定義的,全局結(jié)果定義完成后,該 package 下的所有 action 都能來使用它們。
其余 package 如果也想來使用這些結(jié)果,那么需要通過 extends 來繼承該 package 才能使用。
配置默認 action
<package name="default" extends="struts-default">
<default-action-ref name="invalidAction" />
<action name="invalidAction">
<result type="redirect">/index.jsp</result>
</action>
</package>
在沒有配置默認 action 之前,若訪問一個不存在的 action,那么服務器端將報出錯誤,客戶端瀏覽器得到的是 HTTP ERROR: 404 的錯誤提示頁面。
在配置好默認的 action 之后,若訪問一個不存在的 action,那么這個默認的 action 將被執(zhí)行并將執(zhí)行完成的結(jié)果視圖發(fā)回給客戶端。
另外,<default-action-ref> 節(jié)點需要在 <action> 節(jié)點之前聲明,否則在啟動時將報出錯誤。
package 的運用
<struts>
<package name="first" namespace="/first" extends="struts-default">
<action name="access">
<result>/pages/package/first.jsp</result>
</action>
</package>
<package name="second" extends="struts-default">
<action name="access">
<result>/pages/package/second.jsp</result>
</action>
</package>
<package name="third" extends="struts-default" abstract="true">
<global-results>
<result>/pages/package/third.jsp</result>
</global-results>
</package>
<package name="fourth" namespace="/fourth" extends="third">
<action name="access" />
</package>
</struts>
這里總共配置了4個 package,其中一個是抽象的,其余3個 package 中分別定義了一個 action,action 節(jié)點的 class 和 method 屬性不指定 ( 使用默認 ),并且 action 的 name 屬性都指定為 access ( 極端示例,切勿效仿 ☺ )。
訪問 first package 下的 action 的方式為:/first/access.action
訪問 second package 下的 action 的方式為:/access.action 或 /xxx/access.action 或 /xxx/yyy/access.action ( xxx、yyy 代表任意串 )
訪問 fourth package 下的 action 的方式為:/fourth/access.action
不知道你注意了沒有,這里的 second package 的命名空間是沒有指定的,也就是說它能捕獲所有的命名空間串。那好,現(xiàn)在問題來了,當訪問 /first/access.action 的時候,得到的視圖為什么是 first.jsp 而不是 second.jsp 呢?這是不是跟 package 節(jié)點在配置文件中出現(xiàn)的先后順序有關(guān)系呢?( 有過 WEB 開發(fā)的都知道,配置文件中節(jié)點的先后順序有時候是很重要的 )。這個很明顯,當訪問 /fourth/access.action 的時候,得到的是 third.jsp 而不是 second.jsp。事實上,Struts2 是首先根據(jù) URL 中的命名空間去相對應的 package 下查找 action,如果查找不到,才到默認的命名空間的 package 中去查找 action,如果有多個 package 都使用了默認的命名空間,這個時候才是根據(jù) package 出現(xiàn)的先后順序來查找 action 的。
action 的運用
package fan.tutorial.action;
import com.opensymphony.xwork2.Action;
public class ExampleAction implements Action {
public String execute() {
System.out.println("--- ExampleAction[execute] ---");
return SUCCESS;
}
public String launch() {
System.out.println("--- ExampleAction[launch] ---");
return "launch";
}
public String load() {
System.out.println("--- ExampleAction[load] ---");
return "load";
}
}
<struts>
<package name="simple" namespace="/simple" extends="struts-default">
<action name="example" class="fan.tutorial.action.ExampleAction">
<result name="load">/pages/example/load.jsp</result>
<result name="launch">/pages/example/launch.jsp</result>
<result name="success">/pages/example/success.jsp</result>
</action>
<action name="example2" class="fan.tutorial.action.ExampleAction" method="load">
<result name="load">/pages/example/load.jsp</result>
<result name="launch">/pages/example/launch.jsp</result>
<result name="success">/pages/example/success.jsp</result>
</action>
</package>
</struts>
這里配置了2個 action,不同的是,第2個 action 使用了 method 屬性,那么當訪問 /simple/example2.action 的時候,由 method 指定的方法將被執(zhí)行。
而第1個 action 沒有指定 method 屬性,那么當訪問 /simple/example.action 的時候,默認執(zhí)行的是 execute 方法。
action 動態(tài)方法的調(diào)用
Struts2 Action 動態(tài)方法調(diào)用非常簡單,就是在 action 名稱后面使用 "!" 來鏈接需要執(zhí)行的方法的名稱就可以了。以上面的配置為例,如想調(diào)用 ExampleAction 的 launch 方法,只需要訪問 /simple/example!launch.action 就可以了。
使用通配符映射 action
<struts>
<package name="wildcard" namespace="/wildcard" extends="struts-default">
<action name="*_*" class="fan.tutorial.action.{1}Action" method="{2}">
<result name="{2}">/pages/example/{2}.jsp</result>
</action>
</package>
</struts>
通配符 "*" 匹配的值用符號 {n} 來訪問得到。第1個 "*" 用 {1} 來訪問,其余的以此類推。
使用通配符后,如果想執(zhí)行 ExampleAction 的 launch 方法,訪問 /wildcat/Example_launch.action 即可。
需要注意的是,這里的 Example 必須是要大寫字母開頭的,因為它是用來定位我們的 Action 類路徑的,它必須與你的類名稱保持高度一致。
dispatcher 結(jié)果類型的運用
package fan.tutorial.action;
import com.opensymphony.xwork2.Action;
public class LoginAction implements Action {
private String username;
private String password;
public String execute() {
System.out.println("**************************");
System.out.println("LoginAction: ");
System.out.println("username = " + username + ", password = " + password);
System.out.println("**************************");
return SUCCESS;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package fan.tutorial.action;
import com.opensymphony.xwork2.Action;
public class ManagerAction implements Action {
private String username;
private String password;
public String execute() {
System.out.println("**************************");
System.out.println("ManagerAction: ");
System.out.println("username = " + username + ", password = " + password);
System.out.println("**************************");
return SUCCESS;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
<struts>
<package name="result" namespace="/result" extends="struts-default">
<action name="login" class="fan.tutorial.action.LoginAction">
<result type="dispatcher">/pages/result/login.jsp</result>
</action>
<action name="manager" class="fan.tutorial.action.ManagerAction">
<result type="dispatcher">/pages/result/manager.jsp</result>
</action>
</package>
</struts>
<html>
<h1>${username}, ${password}</h1>
</html>
dispatcher 是默認的結(jié)果類型,也是最常用的結(jié)果類型。
當訪問 /result/login.action?username=u&password=p 的時候,在 login.jsp 中輸出相應的信息,這個比較簡單,就不多說了。
chain 結(jié)果類型的運用
<struts>
<package name="result" namespace="/result" extends="struts-default">
<action name="login" class="fan.tutorial.action.LoginAction">
<result type="chain">manager</result>
</action>
<action name="manager" class="fan.tutorial.action.ManagerAction">
<result type="dispatcher">/pages/result/manager.jsp</result>
</action>
</package>
</struts>
訪問 /result/login.action?username=u&password=p,在控制臺可以看到,LoginAction 和 ManagerAction 的 execute 方法依次被執(zhí)行并打印出相應的信息,請求中攜帶的數(shù)據(jù)在兩個 Action 中被共享,最終在 manager.jsp 中顯示相應的信息。
需要注意的是,在 chain 中不能為 action 指定擴展名,如 manager.action 等是不正確的。
redirect 結(jié)果類型的運用
<struts>
<package name="result" namespace="/result" extends="struts-default">
<action name="login" class="fan.tutorial.action.LoginAction">
<result type="redirect">/pages/result/login.jsp</result>
</action>
<action name="manager" class="fan.tutorial.action.ManagerAction">
<result type="redirect">
/pages/result/manager.jsp?username=${username}&password=${password}
</result>
</action>
</package>
</struts>
當訪問 /result/login.action?username=u&password=p 的時候,控制臺打印出了接收到的參數(shù)的信息,但是 login.jsp 頁面中不會顯示參數(shù)信息,這是由于重定向引起的,上面已經(jīng)有提及到,這里就不再贅述。
若想使用 redirect 又不想丟失一些你感興趣的數(shù)據(jù),那么,可以采用像第2個 action 的配置方式,在重定向的時候,重新把一些必要的信息傳回去就可以了。
需要注意的是,若有多個參數(shù),不能像平常那樣使用 "&" 來連接,而是需要使用它的實體名稱 ( & ) 來連接。否則,工程在啟動的時候是會報出錯誤的。
redirectAction 結(jié)果類型的運用
<struts>
<package name="result" namespace="/result" extends="struts-default">
<action name="login" class="fan.tutorial.action.LoginAction">
<result type="redirectAction">manager</result>
</action>
<action name="login_alias" class="fan.tutorial.action.LoginAction">
<result type="redirectAction">
manager?username=${username}&password=${password}
</result>
</action>
<action name="manager" class="fan.tutorial.action.ManagerAction">
<result type="dispatcher">/pages/result/manager.jsp</result>
</action>
</package>
</struts>
當訪問 /result/login.action?username=u&password=p 的時候,在控制臺,LoginAction 的 execute 方法執(zhí)行并將接收得到的參數(shù)信息打印了出來,
而 ManagerAction 的 execute 方法執(zhí)行打印出來的參數(shù)信息是 null,說明執(zhí)行到 ManagerAction 的時候,之前的 HTTP 請求參數(shù)已經(jīng)丟失了,同樣的,這是由于重定向造成的。
如果不想丟失數(shù)據(jù),可以參考 login_alias 的配置方式。需要注意的問題和上面 redirect 提到的是一樣的。實際上,這里的 redirectAction 也可以換成 redirect 的,它們達到的效果是一樣的。
stream 結(jié)果類型的運用
考慮到文章篇幅過長,這個將留到下一篇文章中來專門介紹。這里暫且略過。
配置動態(tài)結(jié)果
package fan.tutorial.action;
import java.util.Random;
import com.opensymphony.xwork2.Action;
public class DynamicResultAction implements Action {
private String resultView;
public String execute() {
if(new Random().nextInt(100) % 2 == 0){
resultView = "even";
}else{
resultView = "odd";
}
return SUCCESS;
}
public String getResultView() {
return resultView;
}
}
<struts>
<package name="result" namespace="/result" extends="struts-default">
<action name="dynamic" class="fan.tutorial.action.DynamicResultAction">
<result>/pages/result/${resultView}.jsp</result>
</action>
</package>
</struts>
這里使用了 ${resultView} 表達式,這要求 Action 類中必須有一個 public String getResultView() 方法。
struts-xml.zip