Struts 概述
隨著MVC 模式的廣泛使用,催生了MVC 框架的產生。在所有的MVC 框架中,出現最早,應用最廣的就是Struts 框架。
Struts 的起源
Struts 是Apache 軟件基金組織Jakarta 項目的一個子項目, Struts 的前身是CraigR. McClanahan 編寫的JSP Model2 架構。
Struts 在英文中是"支架、支撐"的意思,這表明了Struts 在Web 應用開發中的巨大作用,采用Struts 可以更好地遵循MVC 模式。此外, Struts 提供了一套完備的規范,以基礎類庫,可以充分利用JSP/Servlet 的優點,減輕程序員的工作量,具有很強的可擴展性。
Struts優點
提高開發效率,減輕了程序員的工作量,降低了重復代碼(降低代碼冗余),文件不再臃腫。
可以規范軟件開發的行為。ActionForm為我們封裝請求數據
增加代碼的擴展性、移植性
提高代碼的可重用性、可讀性,無需多個Servlet多個方法
Action轉發頁面只須配置跳轉資源即可,無效全路徑、硬編碼。降低代碼的耦合性
Struts 架構的工作原理
1. Model 部分
Struts 的Model 部分由ActionForm和JavaBean 組成。其中ActionForm用于封裝用戶請求參數,所有的用戶請求參數由系統自動封裝成ActionForm 對象:該對象被ActionServlet轉發給Action; 然后Action 根據ActionForm里的請求參數處理用戶請求。JavaBean 則封裝了底層的業務邏輯,包括數據庫訪問等。在更復雜的應用中,JavaBean所代表的絕非一個簡單的JavaBean,可能是EJB 組件或者其他的業務邏輯組件。該Model 對應圖3 .4的Model 部分。
2. View 部分
Struts 的View 部分采用JSP 實現。Struts 提供了豐富的標簽庫,通過這些標簽庫可以最大限度地減少腳本的使用。這些自定義的標簽庫可以實現與Model 的有效交互,并增加了顯示功能。對應圖的JSP 部分。
整個應用由客戶端請求驅動,當客戶端請求被ActionServlet 攔截時, ActionServlet根據請求決定是否需要調用Model 處理用戶請求,當用戶請求處理完成后,其處理結果通過JSP 呈現給用戶。
3. Controller部分
Struts 的Controller 由兩個部分組成。
·系統核心控制器—攔截用戶請求ActionServlet 派發請求
·業務邏輯控制器—處理用戶請求的Action,處理業務邏輯
其中,系統核心控制器是一個ActionServlet。該控制器由Struts 框架提供,繼承HttpServlet類,因此可以配置成一個標準的Servlet。該控制器負責攔截所有Http請求,然后根據用戶請求決定是否需要調用業務邏輯控制器,如果需要調用業務邏輯控制器,則將請求轉發給Action 處理,否則直接轉向請求的JSP 頁面。業務邏輯控制器負責處理用戶請求,但業務邏輯控制器本身并不具有處理能力,而是調用Model 來完成處理。業務邏輯控制器對應圖3 .4中的Action 部分。
下面結合圖3.7 對Struts 的工作流程作詳細的講解。
Web 應用都是請求一響應的程序結構。程序是由客戶端Client 發出Http 請求開始的,客戶端請求被ActionServlet 攔截。在ActionServlet 處,有兩種情況:
·要求邏輯控制器處理的請求:
·簡單轉發的請求。
對于第一種的請求,ActionServlet 需要調用對應的Action。因此ActionServlet 將請求轉發到Action ,如果請求還配置了對應的FormBean,則ActionServlet 還負責用請求參數填充ActionForm,此時如果ActionForm還沒有創建。ActionServlet會幫我們創建一個可以用的ActionForm,如果ActionForm已經創建就直接給我們用, ActionForm 的實質就是JavaBean,專門用于封裝請求參數。并且在次期間,如果ActionForm如果有驗證方法,會去執行驗證方法,如果驗證通過會進入Action中。驗證失敗,會跳轉到Action配置的input資源頁面。
此時的Action 將無須從HTTP Request 中獲取請求參數,而是從ActionForm 中獲得請求參數。Action 獲得請求參數后,調用Model 對象由JavaBean 處理用戶請求。Action處理完用戶請求之后,將處理結果包裝成ActionForward,回送給ActionServlet。
由于ActionForward 對象封裝了JSP 資源的映射。因此, ActionServlet 知道調用合適的JSP 資源表現給客戶端。
對于第二種請求, HTTP 請求無須Action 處理,只是對普通資源的請求,作為超級鏈接的替代。因為ActionServlet 直接將該請求轉發給JSP 資源,既不會填充ActionForm,也無須調用Action 處理。
JSP 頁面在表現之前,還需要調用對應的JavaBean,此處的JavaBean 不再是包含業務邏輯的JavaBean,而是封裝了處理結果的普通vo (值對象)。JSP 頁面根據vo 的值,可能利用JSTL 或者Struts 的標簽庫來生成HTTP 響應給客戶端。總之JSP 應盡量避免使用Java 腳本。
Action配置
path是我們請求訪問的路徑,如果用struts標簽,會默認加上.do的后綴。ActionServlet攔截到*.do的請求后,就進行相應的業務處理,然后派發到path對應的Action;
name是Action對象的ActionForm,ActionForm是封裝請求的信息,如表單
attribute和name一樣,可以省略,在省略的情況下用name。都是對應ActionForm
type是Action對象對應的文件路徑,含包名
scope是ActionForm的作用域,默認request
parameter后帶方法名稱,即請求所執行的方法
forward是轉發后的資源頁面
ActionForward配置
name邏輯名稱和Action中的mapping.forward參數對應
path對應映射的JSP頁面
redirect是否重定向請求
forward有全局和局部的2種,如果當前Action配置的forward資源在當前配置的Action中沒有找到,然后回到全局的forward資源中查找。局部優先全局
ActonForm配置
name是form的名稱
type是form的包名+文件名
ActionForm還有動態ActionForm、驗證ActionForm
國際化I18N(Internationalization)
目的:是適應更多的、更好的用戶界面
Java 程序的國際化主要通過如下三個類完成。
java.util. ResourceBundle: 對應用于加載一個資源包。
java.util.Locale: 對應一個特定的國家/區域及語言環境。
java.text.MessageFormat: 用于將消息格式化。
為了實現程序的國際化,必須先提供程序所需要的資源文件。資源文件的內容是和很多key-value 對。其中key 是程序使用的部分,而value 則是程序界面的顯示。
資源文件的命名可以有如下三種形式。
baseName _language_country.properties。
baseName _language.properties。
baseNarne.properties 。
其中baseName 是資源文件的基本名,用戶可以自由定義。而language 和count可都不可隨意變化,必須是Java 所支持的語言和國家。
1.國際化支持的語言和國家
事實上, Java 也不可能支持所有國家和語言,如需要獲取Java 所支持的語言和國家,可調用Locale 類的getAvailableLocale 方法來獲取。該方法返回一個Locale 數組,該數組里包含了Java 所支持的語言和國家。
2. 編寫國際化所需的資源
國際化所需的資源文件內容是key-value 對,下面提供了兩個資源文件,這兩個資源文件很簡單,只包含一個key-value 對。
下面是MyResource.properties 的文件的內容:
資源文件的內容: key-value 對。
msg=Hello , {O} Today is {1}.
下面是MyResource_zh_CN.properties 文件的內容:
資源文件的內容: key-value 對
msg=你好. {O} 今天是{l}。
所有資源文件的key 都是相同的,只是value 會隨國家和語言的不同而變化。
3.程序從哪里獲取資源呢?
在ResourceBundle 加載資源時按如下順序搜索。
搜索所有國家和語言都匹配的資源文件,例如,對于簡體中文的環境,先搜索如下文件:
MyResource_zh_CN.properties
如果沒有找到國家和語言都匹配的資源文件,則再搜索語言匹配的文件,即搜索如下文件:
MyResource_zh.properties
如果上面的文件依然無法搜索到,則搜索baseNarne 匹配的文件,即搜索如下文件:
MyResource.properties
4. 使用類文件代替資源文件
Java 也允許使用類文件代替資源文件,即將所有的key-value對存入class 文件,而不是屬性文件。
用來代替資源文件的Java 文件必須滿足如下條件。
·類的名字必須為baseNarne_language_country,這與屬性文件的命名相似。
·該類必須繼承ListResourceBundle,并重寫getContents 方法,該方法返回Object數組,該數組的每一個項都是key=value 對。
eg:下面的類文件可以代替上面的屬性文件:
public class MyResource_zh_CN extends ListResourceBundle {
// 定義資源
private final Object myData[][] = { "msg" , " {0}您好!今天是{l} "};
//重寫方法getContents()
public Object[] [] getContents() {
//該方法返回資源的key-value對
return myData;
}
}
如果系統同時存在資源文件及類文件,則系統將以類文件為主,而不會調用資源文件。對于簡體中文的Locale, ResourceBundle 搜索資源的順序是:
(1) baseName zh CN.class 。
(2) baseNarne_zh_CN.properties。
(3) baseNarne zh.class 。
(4) baseNarne_zh.properties。
(5) baseNarne.class。
(6) baseNarne.properties。
當系統按上面的順序搜索資源文件時,如果前面的文件不存在,則會使用下一個:如果一直找不到對應的文件,系統將拋出異常。
struts加載資源文件
資源文件的加載通過struts-config.xml文件來配置,加載資源文件應從Web 應用的WEB-INF/classes路徑開始加載。因此,資源文件必須放在WEB-INF/classes路徑或該路徑的子路徑下。如果直接放在WEB-INF/classes 路徑下,在配置資源文件時,直接指定資源文件的baseName 即可。但如果放在子路徑下,則必須以包的形式配置。
動態ActionForm
Why?當一個form表單的屬性、字段非常多的情況下,需要我們不斷的修改、添加ActionForm中的屬性,并提供getter、setter方法。雖然這個類比較簡單,但是大量重復的getter、setter方法也是比較繁瑣的。這個時候struts的動態ActionForm就派上用場了。使用動態ActionForm 的目的是為了減少代碼的書寫量,但是相對在配置方面要復雜些。
配置動態ActionForm
所有的動態ActionForm 的實現類都必須是org.apache.struts.action.DynaActionForm類,或者是它的子類。使用動態ActionForm 與前面不同的是:因為系統不清楚動態ActionForm 的屬性,所以必須在配置文件中配置對應的屬性。可以使用form-property 元素來配置動態ActionForm 的屬性。
<!一配置動態ActionForm,動態Aciton 必須使用烏rnaActionForm 一〉
<form-bean name="loginForm" type="org.apache.struts.action.DynaActionForm">
<!一配置ActionForm的屬性: username-->
<form-property name="username" type="java.lang.String"/>
<! 配置ActionForm的屬性: pass-->
<form-property name="pass"type="java.lang.String"/>
</form-bean>
<!-- 配置Action中的path , type , name 屬性>
<action path="/login" type="com.hoo.LoginAction" name="loginForm">
<!一配置兩個局部Forward-->
<forward name="welcome" path="/WEB-INF/jsp/welcome.jsp"/>
<forward name="input" path="/login.jsp"/>
</action>
從上面的配置文件可看出,動態ActionForm 的配置必須增加form-property 元素,每個屬性必須對應一個form-property元素。
form-property元素包含兩個屬性。
name: 屬性的名字,必須與JSP 頁面的表單域的名字相同。
type: 屬性的類型。
使用動態ActionForm
//必須重寫該核心方法,該方法actionForm 將表單的請求參數封裝成值對象
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
//將ActionForm強制類型轉換為DynaActionForm
DynaActionForm loginForm = (DynaActionForm)form;
//從ActionForm中解析出請求參數: username
String username = (String)loginForm.get("username");
//從ActionForm中解析出請求參數: password
String pass = (String)loginForm.get("pass");
//后面的處理與前一個示例的Action 相同。
…………
}
使用動態ActionForm 時,請求參數必須使用DynaActionForm的getter 方法獲取。
DynaActionForm 的getter 方法主要有如下三個。
Object get(java.lang.String name): 根據屬性名返回對應的值。
Object get(java.lang.String name, int index): 對于有多個重名表單域的情況, Struts將其當成數組處理,此處根據表面域名和索引獲取對應值。
Object get(java.lang.String name, java.lang.String key): 對于使用Map 屬性的情況,根據屬性名及對應key. 獲取對應的值。
Struts 的標簽庫
Struts 提供了大量的標簽庫,用于完成表現層的輸出。借助于Struts 的標簽庫,可避免在JSP 中嵌入大量的Java 腳本,從而提高代碼的可讀性。
Struts 主要提供了如下三個標簽庫。
A、 html: 用于生成HTML 的基本標簽。
B、 bean: 用于完成程序國際化,輸出Struts 的ActionForm 的屬性值等。
C、 logic: 用于完成循環、選擇等流程控制。
使用html 標簽庫
Struts 為htrnl 的大部分標簽提供了對應的htrnl 標簽, htrnl 所支持的標簽大致有如下。
* base: 表現成一個HTML 的<base>標簽。
* button: 表現成一個按鈕,該按鈕默認沒有任何動作。
* cancel: 表現成一個取消按鈕。
* checkbox: 表現成一個Checkbox 的輸入框。
* error: 用于輸出數據校驗的出錯提示。
* file: 表現成一個文件瀏覽輸入框。
* form: 表現成一個form 域。
* frame: 表現成一個HTML<frame>標簽。
* hidde: 表現成一個隱藏域。
* htrnl: 表現成HTML 的<htrnl>標簽。
* image: 表現成表單域的image 域。
* img: 表現成一個HTML 的img 標簽。
* javascrit: 表現成JavaScript 的校驗代碼,這些校驗代碼根據ValidatorPlugIn 生成。
* link: 表現成HTML 的超級鏈接。
* messages: 用于輸出Struts 的各種提示信息,包括校驗提示。
* multibox: 表現成一個Checkbox 輸入框。
* option: 表現成選擇框的一個選項。
* password: 表現成一個密碼輸入框。
* radio: 表現成一個單選輸入框。
* reset: 表現成一個重設按鈕。
* rewrite: 表現成一個URL 。
* select: 表現成一個列表選擇框。
* submit: 表現成一個提交按鈕。
* text: 表現成一個單行文本輸入框。
* textarea: 表現成一個多行文本框。
使用bean 標簽庫
bean 標簽庫主要用于輸出屬性值、提示消息及定義請求參數等。下面是bean 標簽庫的常用標簽。
* cookie: 將請求的cookie 的值定義成腳本可以訪問的JavaBean 實例。
* define: 將某個bean 的屬性值定義成腳本可以訪問的變量。
* header: 將請求頭的值定義成腳本可以訪問的變量。
* include: 將某個JSP 資源完整定義成一個bean 實例。
* message: 用于輸出國際化信息。
* page: 將page Context 中的特定項定義成一個bean 。
* parameter: 將請求參數定義成腳本可以訪問的變量。
* resource: 加載Web 應用的資源,并將其變成JavaB eano
* struts: 用于將某個Struts 的內部配置成一個bean 。
* write: 用于輸出某個bean 的屬性值。
使用logic 標簽庫
logic 標簽庫是使用最頻繁,相對復雜的標簽庫。logic 標簽庫主要用于完成基本的流程控制,比如循環及選擇等。
logic 標簽庫主要有如下標簽。
* empty: 如果給定的變量為空或者為空字符串,則就計算并輸出標簽體的內容。
* equal: 如果給定變量與特定的值相等,則會計算并輸出該標簽體的內容。
* forward: 將某個頁面的控制權forward 確定的ActionForward 項。
* greaterEqual: 如果給定變量大于或等于特定的值,則會計算并輸出標簽體的內容。
* greaterThan: 如果給定變量大于特定的值,則會計算井輸出標簽體的內容。
* iterate: 通過遍歷給定集合的元素,對標簽體的內容進行循環。
* lessEqual: 如果給定變量小于或等于特定的值,則會計算并輸出標簽體的內容。
* lessThan: 如果給定變量小于特定的值,則會計算并輸出標簽體的內容。
* match: 如果特定字符串是給定消息合適的子字符串,則會計算并輸出標簽體的內容。
* messagesNotPresent: 如果請求中不包含特定的消息內容,將計算并輸出標簽體的內容。
* messagesPresent: 如果請求中包含特定的消息內容,則計算并輸出標簽體的內容。
* notEmpty: 如果給定的變量既不為空,也不是空字符串,則計算并輸出標簽體的內容。
* notEqual: 如果給定變量不等于特定的值,則會計算并輸出標簽體的內容。
* notMatch: 如果特定宇符串不是給定消息合適的子字符串,則會計算并輸出標簽體的內容。
* notPresent: 如果特定的值沒有出現在請求中,則計算并輸出標簽體的內容。
* present: 如果特定的值出現在請求中,則計算并輸出標簽體的內容。
* redirect: 重定向頁面。
Struts 的數據校驗
數據校驗也稱為輸入校驗,指導對用戶的輸入進行基本過濾,包括必填宇段,宇段必須為數字及兩次輸入的密碼必須相匹配等。這些是每個MVC 框架都應該完成的任務,Struts 提供了基本的數據校驗,如果結合commons-validator, Struts 則擁有強大的校驗框架,包括進行客戶端的JavaScript 校驗等。
Struts 的數據校驗大致有如下幾種方式:
ActionForm 的代碼校驗。
Action 里的代碼校驗。
結合commons-validator.jar 的校驗。
ActionForm 的代碼校驗
ActionForm 的代碼校驗是最基本的校驗方式。這種校驗方式是重寫ActionForm 的validate 方法,在該方法內對所有的宇段進行基本校驗。如果出現不符合要求的輸出,則將出錯提示封裝在ActionError 對象里,最后將多個ActionError 組合成ActionErrors 對象,該對象里封裝了全部的出錯提示。并將錯誤信息用<html:error/>展現在配置的input的失敗頁面上。
Action 的代碼校驗
在Action 里通過代碼完成輸入校驗,是最基本,也最容易使用的方法。與最初的MVC 設計相似,在調用業務邏輯組件之前,先對數據進行基本校驗。這是最傳統也是最原始的方法。
這種校驗方式非常容易理解,所有的代碼都需要程序員自己控制,相當靈活。
但有如下幾個不方便之處。
·用戶需要書寫大量的校驗代碼,使程序變得煩瑣。
· 數據校驗應該在填充ActionForm里完成,最好能在客戶端完成校驗,而不是推遲到Action 里才完成數據校驗。
注意:在實際的使用中,這種校驗方式不僅程序開發復雜,且性能也不高。
結合commons-validator.jar 的校驗
借助于commons-validator.jar 的支持, Struts的校驗功能非常強大,幾乎不需書寫任何代碼。不僅可以完成服務器端校驗,同時還可完成客戶端校驗,即彈出Javascript 提示。
使用commons-validator.jar 校驗框架時,有如下幾個通用配置。
·增加校驗資源。
·利用ValidatorPlugIn 加載校驗資源。
·ActionForm 使用ValidatorForm 的于類。
下面分別通過三個示例講解這三種校驗:基本的校驗、對動態ActionForm 執行校驗及彈出JavaScript 校驗提示。
1. 繼承ValidatorForm 的校驗
如果需要使用commons-validator 框架,請按如下步驟進行。
(1) Struts 的ActionForm必須是ValidatorForm的子類,提供驗證屬性字段的getter、setter方法
(2) 編寫表單域時必須滿足校驗規則。校驗規則都由規則文件控制,規則文件有以下兩個。
* validator-rules.xml 文件
* validation.xml 文件
第一個文件可在Struts 的解壓縮后的文件夾的lib 下找到,將該文件復制到WEB-INF
2. common-validator支持的校驗規則
common-validator支持的校驗規則非常豐富,特別是mask 和validwhen 兩個規則,
極大地豐富了該校驗框架的功能。
常用的校驗規則有如下幾種。
* required: 必填。
* va1idwhen: 必須滿足某個有效條件。
* minlength: 輸入必須大于最小長度。
* maxlength: 輸入必須小于最大長度。
* mask: 輸入匹配正確的表達式。
* byte: 輸入只能是一個byte 類型變量。
* short: 輸入只能是一個short 類型變量。
* integer: 輸入只能是一個integer 變量。
* long: 輸入只能是一個long 變量。
* float: 輸入只能是一個float 變量。
* double: 輸入只能是一個double 變量。
* date: 輸入必須是一個日期。
* intRange: 輸入的數字必須在整數范圍內。
* floatRange: 輸入的數字必須在單精度浮點數范圍內。
* doubleRange: 輸入的數字必須在雙精度浮點數范圍內。
* email: 輸入必須是有效的E-mail 地址。
* uri: 輸入必須是有效的uri 地址。
3.使用DynaValidatorForm 的校驗
即使不書寫ActionForm,也可以利用cornmon-validator 校驗框架。此時使用的ActionForm 的實現類,必須既是動態Form ,也是驗證Form,DynaValidatorForm 就是滿足這兩個條件的Form。
4. 彈出客戶端JavaScript提示
如需要彈出客戶端JavaScript 校驗非常簡單,無須修改其他配置文件,只需修改登錄使用的JSP 頁面的兩個地方。
(1) 為form 元素增加onsubmit="return validateXxxForm(this);"屬性,其中的XxxForm就是需要校驗的form 名,與struts-config.xrnl中配置的form-bean 的name 屬性一致,也與validation.xrnl文件中需要校驗的form 的name 屬性一致。
(2) 增加<html:javascript formName="xxxForm"/> ,其中xxxForm 是需要校驗的form 名。
注意:即使使用了客戶端技驗規則,也不要刪除頁面的htm1 :rnessages 標簽。因為該標簽會在客戶端技驗通過,而在服務器端技驗并未通過時彈出提示。
Struts 的異常框架
Struts 1.1 版本中加入了對異常的處理,稱之為Exception Handling,標志著作為一個整體的框架, Struts 越來越趨于成熟。
在以前的Struts 開發過程中,對于異常的處理,主要是采用手動處理的方式:如通過try/catch 等捕獲異常:然后將定制個性化的,比較詳細的錯誤信息放進ActionMessage中:最后在返回頁面中把這些錯誤信息反饋給用戶。
對于異常的原始信息,不管是最終用戶還是開發員都不希望看到。
借助于Struts 的異常框架,異常處理只需通過struts-config.xm1文件定義即可。根據異常定義的位置不同,異常可分為局部異常和全局異常兩種。
·局部異常作為action 的子元素中定義。
·全局異常在globa1-excetpions 元素中定義。
異常定義的格式如下:
<exception key="keyNarne" type="ExceptionNarne" scope="scope" path="uri"/>: 當Struts 出現ExceptionNarne 的異常時,頁面自動轉向uri 指向的資源,并在該頁面輸出keyName 對應的國際化中的出錯提示。
幾種常用的Action
除了基本的Action 之外, Struts 還提供了幾個其他類型的Action ,這些Action 大大豐富了Struts 的功能。下面介紹如下兒個常用的Action 。
* DispatchAction: 能同時完成多個Action 功能的Action 。
* ForwardActon: 該類用來整合Struts 和其他業務邏輯組件,通常只對請求作有效性檢查。
* IncludeAction: 用于引入其他的資源和頁面。
* LookupDispatchAction: DispatchAction 的子類,根據按鈕的key ,控制轉發給action的方法。
* MappingDispatchAction: DispatchAction 的子類,一個action 可映射出多個Action地址。
* SwitchAction: 用于從一個模塊轉換至另一個模塊,如果應用分成多個模塊時,就可以使用SwitchAction 完成模塊之間的切換。
DispatchAction
在該action 的配置中,增加了parameter屬性,該屬性用于指定參數名,即Struts 將根據該參數的值調用對應的方法。為了讓請求增加method 的參數,method參數對應的是要請求執行的方法。
<action path="/login" type="com.hoo.LoginAction" name="loginForm" scope="request" validate="true" input="login.jsp" parameter="method">
<forward name="success" path="/welcome.jsp"/>
</action>
Login.do?method=login
MappingDispatchAction
可將同一個Action 的不同方法映射成多個Action URI ,這種Action 的寫法與DispatchAction 非常相似,同樣不需要重寫execute 方法,而是將書寫多個自定義的方法。這些方法除了方法名與execute 方法不同外,其他的參數列表及異常處理完全一樣。
<!-- 配置第一個Action. 實現類是com.hoo.LoginAction , parameter 為add-->
<action path="/add" type="com.hoo.LoginAction" name="loginForm" scope="request" validate="true" input="login.jsp" parameter="add">
<forward name="success" path="/welcome.jsp"/>
</action>
<! 配置第二個Action. 實現類是com.hoo.LoginAction , parameter 為modify-->
<action path="/modify" type="com.hoo.LoginAction" name="loginForm" scope="request" validate="true" input="login.jsp" parameter="modify">
<forward name="success" path="/welcome.jsp"/>
</action>
其中,path對應的是請求的地址uri,而parameter是對于當前請求所執行的方法;
注意:使用MappingDispatchAction 并沒有帶來太大的優勢,系統完全可以書寫兩個Action,分別定義兩個不同的action 映射,而其他部分沒有區別。
LookupDispatchAction
LookupDispatchAction也是DispatchAction 的一種,但它的處理更加簡單。該Action也可包含多個處理方法,它可讓處理方法與按鈕直接關聯,無須使用任何的JavaScript腳本。因此可通過重寫getKeyMethodMap方法完成按鈕與Action 中方法的關聯。
//用于關聯按鈕和方法
protected Map getKeyMethodMap() {
Map map = new HashMap();
//如果按鈕標題的key 為button.add. 則提交該按鈕時對應add 方法
map .put ("button. add" , "add");
//如果按鈕標題的key 為button.modify. 則提交該按鈕時對應modify 方法
map.put ("button.modify" , "modify") ;
return map;
}
ForwardAction
如果需要從一個頁面或資源轉換到另一個資源時,直接使用頁面或資源路徑的超級鏈接定位并不是好的做法,這使得控制器沒有機會處理相關的請求事直。
使用ForwardAction可以完成請求的轉發,當控制器調用ForwardAction的perform()方法時,它會使用屬性parameter 所設定的路徑進行forward 的動作。下面是一個設定ForwardAction的例子:
<actlon-mapplngs>
<action path="/welcome" type="org.apache.struts.actions.ForwardAction" parameter="/welcome.jsp"/>
</action-mappings>
該action 僅僅完成轉發,并沒有執行其他的額外動作。頁面控制轉發的代碼如下:
<a href="welcome.do">轉入</a>
當單擊轉入超級鏈接時,將可以轉向ForwardAction中parameter指向的資源。
IncludeAction
IncludeAction的用法與ForwardAction的用法比較相似,區別在于ForwardAction將跳轉到action 定義的資源,而IncludeAction用于引入該action 對應的資源。
下面是IncludeAction定義的源代碼:
<action-mapplngs>
<action path="/welcome" type="org.apache. struts.actions.IncludeAction" parameter="/welcome.jsp"/>
</action-mappings>
該action 用于經welcome.jsp 作為資源導入。
頁面中負責加載該action 所導入資源的代碼如下:
<jsp:include page="welcome.do"/><br>
上面的代碼將會把welcome action 定義的資源導入該頁面。
SwitchAction
SwitchAction 主要用于模塊之間的切換。當一個應用之中存在多個模塊時,使用SwitchAction在不同模塊之間的action 之間切換還是相當方便的。
Struts 的常見擴展方法
Struts 的強大吸引力還來自于它的可擴展性,其擴展性通常有如下三種方式。
·實現PlugIn: 如果需要在應用啟動或關閉時完成某些操作,可以創建自己的PlugIn類。
·繼承RequestProcessor: 如果想在請求被處理中的某個時刻做一些業務邏輯時,可以考慮實現自己的RequestProcessor 類。
·繼承ActionServlet: 如果需要在每次開始處理請求之前,或者處理請求結束之后完成某些操作,可以實現自己的ActionServlet 來完成擴展。
下面分別從三個方面來介紹Struts 的擴展。
實現PlugIn 接口
Struts 已經演示了PlugIn 的擴展方法:與common- validation 的整合。后面還將介紹Spring 與Struts 的整合,也利用了PlugIn 的擴展。
在下面的應用中,系統使用Hibernate 作為持久層,在啟動時創建SessionFactory 實例,并將該SessionFactory 存入application ,在應用關閉時銷毀SessionFactory 。只需如下兩步即可完成此功能。
(1) 實現自己的PlugIn 類。
實現PlugIn 接口必須實現如下兩個方法。
1 void destroy()。
2 void init(ActionServlet serlet, ModuleConfig config) 。
應用啟動時調用init 方法,而應用關閉時則調用destroy 方法。
下面是SessionFactoryLoaderPlugIn 的實現類:
public class SessionFactoryLoaderPlugin implements PlugIn {
//Hibernate 的配置文件
private String configFile;
//應用關閉時,銷毀資源
public void destroy()
System.out.println("系統銷毀SessionFactory");
}
//應用啟動時,完成SessionFactory 的初始化
public void init(ActionServlet actionServlet , ModuleConfig config) throws ServletException
System.out.println("系統以" + getConfigFile() + "為配置文件初始化SessionFactory") ;
//獲取Plugln 配置文件的方法
public String getConfigFile() {
return configFile;
}
// 負責加載Plugln 配置屬性的方法
public void setConfigFile(String configFile) {
this.configFile = configFile;
}
}
在上面的PlugIn 中,并沒有真正初始化SessionFactory ,僅在控制臺打印出字符串來標識創建動作。另外,還提供了configFile 屬性的setter 和getter 方法,這兩個方法負責訪問plugin 元素的configFile 屬性。
( 2 ) 將SessionFactoryLoaderPlugIn 配置在struts-config.xml 文件中。方法與ValidatorPlugIn 的配置并沒有區別,下面是配置SessionFactoryLoaderPlugIn 的代碼:
<plug-in className="hoo.SessionFactoryLoaderPluging">
<set-property property="conf工gFile" value=" WEB-INF/hibernate.cfg.xml"I>
</plug-in>
在配置SessionFactoryLoaderPlugIn 時,配置了configFile 屬性,該屬性用于確定Hibernate 配置文件的文件名。
繼承RequestProcessor
RequestProcessor 是Struts 的核心類,而Struts 的核心控制器是ActionServlet 。但ActionServlet 并未完成真正的處理,只是調用RequestProcessor , RequestProcessor 才是Struts 的核心類。
擴展RequestProcessor 的實例在Spring 中有個示范, Spring 提供的Delegating RequestProcessor 是一個很好的示例。下面示例對RequestProcessor 進行簡單的擴展。
RequestProcessor 包含了如下常見的方法。
* ActionForm processActionForm: RequestProcessor填充ActionForm 時執行該方法。
* Action processActionCreate: RequestProcessor 調用Action 時調用該方法。
* boolean processPreprocess: 預處理用戶請求時執行該方法。
* boolean processValidate: 處理輸入校驗時調用該方法。
擴展RequestProcessor 只需兩步即可。
(2)在struts-config.xml 文件中配置MyRequestProcessor。用戶重寫了RequestProcessor,但Struts 并不知道,必須在struts-config且nl 中配置才可以。
下面是配置MyRequestProcessor 的代碼:
<controller processorClass="lee.MyRequestProcessor" />
該屬性的配置應該放在action-mappings元素之后。
注意:重寫RequestProccessor的方法時,別忘了使用super 來調用父類的動作。如果沒有調用該方法,意味著開發者必須完成Struts 框架所完成的動作。這是不應該的,因為程序員只是在框架中加入額外的處理,并不是要替代Struts。
繼承ActionServlet
如果需要在開始處理請求,或者處理結束之后加入自己的處理時,可對ActionServlet進行擴展。例如解決中文的編碼問題。
ActionServlet 接收處理請求參數時,并不是按GBK 的解碼方式處理請求,因此容易形成亂碼。為了解決該問題,可以強制指定ActionServlet 使用GBK 的解碼方式。
繼承ActionServlet重寫process方法,設置request、response編碼為gbk,然后配置在web.xml中。
版權所有,轉載請注明出處 本文出自:
版權所有,歡迎轉載,轉載請注明出處,謝謝
posted on 2012-01-29 16:48
hoojo 閱讀(1940)
評論(4) 編輯 收藏 所屬分類:
JavaEE 、
Struts