隨筆-57  評論-117  文章-1  trackbacks-0

          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 部分。

          clip_image002

          下面結合圖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 響應給客戶端??傊甁SP 應盡量避免使用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 的異??蚣?/b>

          Struts 1.1 版本中加入了對異常的處理,稱之為Exception Handling,標志著作為一個整體的框架, Struts 越來越趨于成熟。

          在以前的Struts 開發過程中,對于異常的處理,主要是采用手動處理的方式:如通過try/catch 等捕獲異常:然后將定制個性化的,比較詳細的錯誤信息放進ActionMessage中:最后在返回頁面中把這些錯誤信息反饋給用戶。

          對于異常的原始信息,不管是最終用戶還是開發員都不希望看到。

          借助于Struts 的異常框架,異常處理只需通過struts-config.xm1文件定義即可。根據異常定義的位置不同,異??煞譃榫植慨惓:腿之惓煞N。

          ·局部異常作為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中。



          作者:hoojo
          出處:
          blog:http://blog.csdn.net/IBM_hoojo
                   http://hoojo.cnblogs.com
          本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。


          版權所有,轉載請注明出處 本文出自:
          分享道版權所有,歡迎轉載,轉載請注明出處,謝謝
          posted on 2012-01-29 16:48 hoojo 閱讀(1945) 評論(4)  編輯  收藏 所屬分類: JavaEE 、Struts

          評論:
          # re: Struts 筆記 2012-01-30 10:54 | tb
          不錯 謝謝分享了   回復  更多評論
            
          # re: Struts 筆記 2012-02-01 14:04 | 楊Coder
          總結得相當全面啊!  回復  更多評論
            
          # re: Struts 筆記 2012-02-01 16:23 | hoojo
          @楊Coder
          謝謝支持  回復  更多評論
            
          # re: Struts 筆記 2012-02-03 23:37 | allenny
          你這不是1.0版本的Struts嘛  回復  更多評論
            
          主站蜘蛛池模板: 大宁县| 鸡西市| 淮阳县| 霍林郭勒市| 张掖市| 班玛县| 定南县| 莆田市| 西宁市| 肃宁县| 许昌县| 泰安市| 侯马市| 敦化市| 嘉黎县| 乌苏市| 宁南县| 阳朔县| 宜州市| 德惠市| 吴桥县| 叙永县| 滁州市| 宁夏| 呼伦贝尔市| 无棣县| 报价| 泸溪县| 顺义区| 武穴市| 华池县| 饶河县| 汉川市| 那曲县| 明星| 承德市| 抚顺县| 东至县| 兴海县| 景谷| 和政县|