Struts2的Action配置及使用
Struts2預設會載入類載入路徑下的struts.xml、struts-default.xml、struts-plugin.xml三類檔案,其中struts.xml是開發者定義的預設配置檔案,struts-default.xml是Struts2框架自帶的配置檔案,而struts-plugin.xml則是Struts2外掛的預設配置檔案。
struts.xml配置檔案最大的作用是配置Action和請求之間的對應關係,並配置邏輯試圖名和物理檢視資源之間的對應關係。除此之外,struts.xml檔案還有一些額外的功能,例如Bean配置、常量配置、匯入其他配置檔案等。
Struts2
雖然Struts2配置常量有三種方式:通過struts.properties檔案;通過struts.xml配置檔案;通過web應用的web.xml檔案。通常推薦在struts.xml檔案中定義Struts2屬性,而不是在struts.properties檔案中定義Struts2屬性。
可以將一個struts.xml配置檔案分解成多個配置檔案,然後在struts.xml檔案中包含其他配置檔案,示例如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache SoftwareFoundation//DTD Struts Configuration 2.1.7//EN"
"http://struts.apache.org/dtds/struts-2.1.7.dtd">
<!--指定Struts 2配置檔案的根元素 -->
<struts>
<!-- 通過include元素匯入其他配置檔案-->
<includefile="struts-part1.xml"/>
<includefile="struts-part2.xml"/>
...
</struts>
被包含的struts-part1.xml檔案是標準的Struts2配置檔案,一樣包含了DTD資訊、Struts2配置檔案的根元素等資訊。通常,將Struts2的所有配置檔案都放在web應用的WEB-INF/classes路徑下,struts.xml檔案包含了其他的配置檔案,struts.xml檔案由Struts2框架負責載入,從而可以將所有配置資訊都載入進來。
二、實現Action
1.Action介紹
Action是應用的核心,開發者需要提供大量的Action類,並在struts.xml檔案中配置Action。Action類裡包含了對使用者請求的處理邏輯,Action類也被稱為業務控制器。
Action類是一個POJO,包含setter和getter方法,預設處理使用者請求的方法:execute()方法。
ActionSupport是一個預設的Action實現類。如果我們配置的Action沒有指定class屬性(即沒有使用者提供Action類),系統自動使用ActionSupport類作為Action處理類。
2.Action訪問Servlet API
由於Action類不在於ServletAPI耦合,從而能更輕鬆地測試該Action。Web應用中通常要訪問的Servlet API就是HttpServletRequest、HttpSession和ServletContext,這三個介面分別代表JSP內建物件中的request、session和application。
方法一:Struts2提供了一個ActionContext類,Struts2的Action可以通過該類來訪問Servlet API。類中常用方法如下:
Object get(Object key):相當於HttpServletRequest的getAttribute(Stringname)方法。
Map getApplication():返回一個Map物件,該物件模擬了該應用的ServletContext例項。
static ActionContext getContext():靜態方法,獲取系統的ActionContext例項。
Map getParameters():獲取所有請求引數。類似於HttpServletRequest的getParameterMap().
Map getSession():返回一個Map物件,該Map物件模擬了HttpSession例項。
void setApplication(Map application):傳入一個Map的key-value,轉換成application的屬性名、屬性值。
void setSession(Map session):傳入一個Map的key-value,轉換成session的屬性名、屬性值。
方法二:Struts2提供如下幾個介面(需要implements並實現方法):
ServletContextAware:實現該介面的Action可以直接訪問Web應用的ServletContext例項。
ServletRequestAware:實現該介面的Action可以直接訪問使用者請求的HttpServletRequest例項。
ServletResponseAware:實現該介面的Action可以直接訪問伺服器響應的HttpServletResponse例項。
方法三:使用ServletActionContext(工具類)訪問Servlet API:
static PageContext getPageContext():取得Web應用的PageContext物件。
Static HttpServletRequest getRequest():取得Web應用的HttpServletRequest物件。
Static HttpServletResponse getResponse ():取得Web應用的HttpServletResponse物件。
Static ServletContext getServletContext():取得Web應用的ServletContext物件。
3.配置action
實現了Action處理類之後,就可以在struts.xml檔案中配置該Action了。配置Action就是讓Struts2知道哪個Action處理哪個請求,也就是完成使用者請求和Action之間的對應關係。我們可以認為,Action是Struts2的基本“程式單位”;
3.1包和名稱空間
Struts2使用包來組織Action,因此,將Action定義放在包定義下完成,定義Action通過使用<package…/>下的<action…>子元素來完成,而每個package元素配置一個包。
Struts2框架中的核心元件就是Action、攔截器等,Struts框架使用包來管理Action、攔截器。
幾個屬性:
name:這是一個必須屬性,該屬性指定該包的名字,改名字是該包被其他包引用的key。
extends:該屬性是一個可選屬性,指定該包繼承其他包(從而繼承Action、攔截器)。
namespace:該屬性是一個可選屬性,該屬性定義該包的名稱空間。
abstract:該屬性是一個可選屬性,它指定該包是否是一個抽象包(不包含Action定義)。
Strut2-core.jar定義了struts-default抽象包,包含了大量結果型別定義、攔截器定義、攔截器引用定義等,這些都是配置普通Action的基礎,所以開發者定義的package通常應該繼承struts-default包。
如果配置<package…/>時沒有指定namespace屬性,則該包的Action處於預設的包空間下。
當某個包指定名稱空間後,該包下所有的Action處理的URL應該是名稱空間+Action名。
Namespace=”/”為根名稱空間。
找Action順序:先找命名空(包括根名稱空間)間下的,再找預設名稱空間下的。
3.2Action的基本配置
Struts2的Action名字就是它所處理的URL。
通常需要為action元素指定一個class屬性,其中class屬性指定了該Action的實現類。
配置Action時應該配置邏輯試圖和物理檢視資源之間的對應關係,一次一個<result…/>。
Name中開啟斜線支援:將struts.enable.SlashesInActionNames值設定為true。
配置模版如下:
<actionname="login" class="org.crazyit.app.action.LoginAction">
<!--定義三個邏輯檢視和物理資源之間的對映 -->
<resultname="input">/login.jsp</result>
<resultname="error">/error.jsp</result>
<resultname="success">/welcome.jsp</result>
</action>
3.3分配多個Action的處理邏輯
方法一:使用DMI(Dynamic Method Invocation)
動態方法呼叫是指表單元素的action並不是直接等於某個Action的名字,而是以如下形式來指定表單的action屬性:
action=”ActionName!methodName”(放在javascript中)
例子:
網頁中<inputtype=”submit” value=”註冊” onclick=”regist();”>//點註冊按鈕呼叫regist函式
functionregist(){
targetForm = document.forms[0];
targetForm.action= “login!regist”;
}
當用戶點選註冊,系統交給loginAction的regist方法處理。
通過這種方式,我們可以在一個Action中包含多個處理邏輯,並通過為表單元素指定不同action屬性來提交給Action的不同方法,預設是execute方法。
開啟系統的動態方法呼叫是通過設定strut.enable. DynamicMethodInvocation為true。
方法二:指定method屬性及使用萬用字元
示例程式碼:
<?xml version="1.0"encoding="GBK"?>
<!DOCTYPE struts PUBLIC
"-//ApacheSoftware Foundation//DTD Struts Configuration 2.1.7//EN"
"http://struts.apache.org/dtds/struts-2.1.7.dtd">
<struts>
<packagename="lee" extends="struts-default">
<!--使用模式字串定義Action的name,指定所有以Action結尾的請求,
都可用LoginRegistAction來處理,method屬性使用{1},
這個{1}代表進行模式匹配時第一個*所代替的字串-->
<actionname="*Action"class="org.crazyit.app.action.LoginRegistAction"
method="{1}">
<!--定義邏輯檢視和物理檢視之間的對映關係 -->
<resultname="input">/login.jsp</result>
<resultname="error">/error.jsp</result>
<resultname="success">/welcome.jsp</result>
</action>
</package>
</struts>
上面的<actionname=”*Action”…/>元素不是定義了一個普通Action,而是定義了一系列的Action,只要使用者請求的URL是*Action.action的模式,都可以用該Action來處理。該method屬性使用了一個表示式{1},該表示式的值就是name屬性值中第一個*的值。
例如:
使用者請求的URL為loginAction.action,則呼叫lee.LoginRegistAction類的login方法;如果請求的URL為registAction.action,則呼叫lee.LoginRegistAction類的regist方法;
也可以使用兩個萬用字元:
<actionname=”*_*” method=”{2}” class=”actions.{1}”>
Action處理的優先順序:
如果有URL為abcAction.action的請求,如果struts.xml檔案中有abcAction.action則先有它處理,如果沒有,則找*Action或*,*Action並不比*更優先匹配abcAction的請求,而是先找到哪個Action就會由哪個Action來處理使用者的請求。