天天看點

struts2知識小結

                                                                                       struts2知識小結

一、Struts 2應用的開發步驟

         1、首先要先下載下傳Struts 2的jar包,将必須的類庫放入到Web應用下的WEB-INF/lib路徑下。

         2、配置web應用的web.xml配置檔案,配置Struts 2的核心Filter

         3、定義處理使用者請求的Action類

         4、配置Action

         5、配置處理結果和實體試圖資源之間的對應關系

       二、Struts 2的配置

        1、Action通路Servlet API

         Struts 2提供了一個ActionContext,Struts 2的action可以通過該類來通路Servlet API

         該類包含了以下幾個常用的方法:getApplication、getContext、getParameters、getSession、setApplication、setSession通過上面幾個方法我們獲得servlet的對象,并可以對其進行相應的操作。

         當然Action還可以直接通路Servlet API。不過需要實作相應的接口:

         ServletContextAware、ServletRequestAware、ServletResponseAware,實作上面的接口僅僅隻需要實作相應的setXxxxxXxxxx方法就可以了。

         2、配置Action

         package

         Struts 2是使用包來組織管理Action和攔截器等的,每個包可以配置多個Action、多個攔截器、多個攔截器引用,我們可以将包看做是他們的一個集合。

         配置包<package.../>元素的時候必須指定name屬性。該屬性是引用該包的唯一辨別。

         <package..../>元素有如下幾個屬性:name、extends、namespace、abstract。

         配置如下:

[html] view plain copy print ?

  1. <package name="mypackage" extends="struts-default"> 
  2. ..................... 
  3. </package> 

<package name="mypackage" extends="struts-default">

.....................

</package>

        Action

        定義Action的時候,像配置<package.../>元素一樣,也要指定一個name屬性,該name屬性的名字就是該Action的名字。但是Action還要指定一個class屬性。該屬性指該Action的實作類。

        注:class屬性并不是必須的,如果我們不為Action指定class屬性,系統會預設使用系統的ActionSupport類。

        一個簡單的Action的配置如下:

[html] view plain copy print ?

  1. <package name="lee"> 
  2.     <action name="login" class="com.app.action.LoginAction"></action>    
  3. </package> 

<package name="lee">

<action name="login" class="com.app.action.LoginAction"></action>

</package>

        Action隻是一個邏輯控制器。它并不會直接作用于浏覽器,也就是說他不會直接對浏覽者生成任何響應。是以,Action處理完使用者請求後,Action需要将指定的視圖資源呈現個使用者。故,在配置Action的時候應該配置邏輯視圖和實體視圖資源之間的對應關系。

配置action的時候,一般還要指定method屬性。該屬性指定實作使用者請求的方法。如果不指定method屬性,系統預設使用execut方法來處理使用者的請求。

        對于method屬性,我們還可以使用通配符。

        如下:

[html] view plain copy print ?

  1. <action name="*Action" class="com.app.action.LoginAction" method="{1}" /> 

<action name="*Action" class="com.app.action.LoginAction" method="{1}" />

         result

         每個<result.../>元素定義邏輯試圖和實體試圖之間的一次映射。

         <result.../>元素應該定義一個name屬性。該屬性指定所配置的邏輯視圖名,也就是相應的action傳回的邏輯視圖名。當然也可以不需要指定name屬性,這時系統會預設使用success。

         <result.../>元素還存在一個type屬性,該屬性指定結果類型。Struts 2支援的結果類型有:Chain、dispatcher、freemarker、httpheader、redirect、stream、velocity、xslt、plainText。當不指定type屬性時,系統預設dispatcher。

         <result.../>元素的配置片段如下:

[html] view plain copy print ?

  1. <action name="login"> 
  2.         <!-- 配置預設結果,省略type屬性,預設dispatcher --> 
  3.         <result>/welcome.jsp</result> 
  4. </action> 

<action name="login">

<!-- 配置預設結果,省略type屬性,預設dispatcher -->

<result>/welcome.jsp</result>

</action>

         上面的配置比較簡單,但是這是Struts 2最基本配置。

         三、Struts 2的異常處理

         我們在實作execute方法的時候,該方法是将異常直接抛出,交給Struts 2架構來處理。                

         這就意味着,我們在處理使用者請求的時候,可以不需要對異常進行處理,直接抛出交給Strust 2處理,Struts 2接收到Action抛出的異常之後,将會根據struts.xml檔案配置的異常映射關系,轉入到指定的視圖資源。

         Strut 2的異常處理機制是通過在struts.xml檔案中配置<exception-mapping.../>元素完成的。配置該元素時,需要指定如下兩個屬性:exception、result。

         如下:

[html] view plain copy print ?

  1. <!-- 定義全局異常映射 --> 
  2.     <global-exception-mappings> 
  3.         <!-- 當Action中遇到SQLException異常時,系統将會轉入到name問sql的結果中 --> 
  4.         <exception-mapping result="sql" exception="java.sql.SQLException"></exception-mapping> 
  5.         <!-- 當Action中遇到Exception異常時,系統将會轉入到name為root的結果中 --> 
  6.         <exception-mapping result="root" exception="java.lang.Exception"></exception-mapping> 
  7.     </global-exception-mappings> 

<!-- 定義全局異常映射 -->

<global-exception-mappings>

<!-- 當Action中遇到SQLException異常時,系統将會轉入到name問sql的結果中 -->

<exception-mapping result="sql" exception="java.sql.SQLException"></exception-mapping>

<!-- 當Action中遇到Exception異常時,系統将會轉入到name為root的結果中 -->

<exception-mapping result="root" exception="java.lang.Exception"></exception-mapping>

</global-exception-mappings>

        對于異常的輸出,我們采用如下方式:

[html] view plain copy print ?

  1. <s:property value="exception"/> 

<s:property value="exception"/>

         四、使用Struts 2國際化

        Strut 2的國際化是建立在java國際化的基礎上的。對于Struts 2的國際化我們一般采用加載全局的國際化資源檔案,加載全局的國際化資源檔案的方式是通過配置常量來實作的。在檔案中配置我們隻需要配置struts.custom.i18n.resoutces常量即可。

        配置struts.custom.i18n.resoutces常量時,該常量的值為全局國際化資源檔案的baseName。一旦指定了全局的國際化資源檔案,既可以實作程式的國際化。

        在struts.xml檔案中我們需要配置如下代碼:

[html] view plain copy print ?

  1. <!--指定Struts 2國際化資源檔案的baseName為messageResource --> 
  2. <constant name="struts.custom.i18n.resoutces" value="messageResource" /> 

<!--指定Struts 2國際化資源檔案的baseName為messageResource -->

<constant name="struts.custom.i18n.resoutces" value="messageResource" />

        對于國際化資源檔案,我們一般采用鍵值對的properties檔案。為了在頁面中輸出國際化資源,我們可以使用Struts 2的<s:text.../>标簽,該标簽的name屬性,指定了國際化資源檔案中的key。

         五、Strut 2的類型轉換

        Struts 2的類型轉換可以基于ONGL表達式。隻要我們把Http參數的命名為合法的ONGL表達式,就可以充分的利用Struts 2的類型轉換機制。

        對于Struts 2内建的類型轉換,我們無需理會,不需要做任何特殊的處理。

        自定義類型轉換

        對于使用者自定義類型轉換器,使用者必須要實作TypeConverter接口。實作自定義類型轉換器需要重寫該方法的convertValue方法。

        該方法是雙向的。可以将字元串轉換成複合類型,也可以将複合類型轉換為字元串。該方法主要是通過toType參數來判斷轉換的方向。

        其實基于Struts 2的自定義類型轉換器,我們可以有更簡單的方法實作。Struts 2提供了一個StrutsTypeString抽象類。該抽象類提供了兩個方法:convertFromString和convertToString。通過實作這個兩個方法就可以實作自定義類型轉換了。

        如下:

[java] view plain copy print ?

  1. public class UserConverter extends StrutsTypeConverter{ 
  2.        //實作将字元串類型轉換為複合類型的方法 
  3.         public object converterFromString(Map context,String[] values,Class toClass){ 
  4.              .............................. 
  5.        } 
  6.       //實作将複合類型轉換為字元串類型的方法 
  7.         public String converterToString(Map context,Object o){ 
  8.              .................... 
  9.        } 

public class UserConverter extends StrutsTypeConverter{

//實作将字元串類型轉換為複合類型的方法

public object converterFromString(Map context,String[] values,Class toClass){

..............................

}

//實作将複合類型轉換為字元串類型的方法

public String converterToString(Map context,Object o){

....................

}

}

        完成了自定義類型轉換器後,還要将類型轉換器注冊到Web應用中去:

        局部類型轉換器:

        <proName>=<ConverterClass>

        <proName>:需要進行類型轉換的屬性

        <ConverterClass>:類型轉換器的實作類

        如下:

[html] view plain copy print ?

  1. user = com.app.converter.UserConverter 

user = com.app.converter.UserConverter

        全局類型轉換器:

        <propType>=<ConvertClass>

        <propType>:需要進行類型轉換的類型

        <ConvertClass>需要進行類型轉換的實作類

        如下:

[html] view plain copy print ?

  1. comcom.app.domain.User = com.app.converter.UserConverter 

com.app.domain.User = com.app.converter.UserConverter

        六、使用Struts 2的輸入校驗

        Struts 2提供了基于驗證架構的輸入校驗,在這種校驗方式下,所有的輸入校驗隻需要編寫簡單的配置檔案,Struts 2的驗證架構将會負責進行伺服器校驗和客服端校驗。    

        1、編寫校驗規則檔案

        校驗規則檔案的根元素是<validator.../>元素,<validator.../>元素可以包含多個<field../>或<validator.../>,他們都用于配置校驗規則。

        配置片段:

[html] view plain copy print ?

  1. <validators> 
  2.     <!-- 校驗Action的name屬性 --> 
  3.     <field name="name"> 
  4.         <!-- 指定name屬性必須滿足必填規則 --> 
  5.         <field-validator type="requiredstring"> 
  6.             <param name="trim">true</param> 
  7.             <message>必須填入名字</message> 
  8.         </field-validator> 
  9.     </field> 
  10. </validators> 

<validators>

<!-- 校驗Action的name屬性 -->

<field name="name">

<!-- 指定name屬性必須滿足必填規則 -->

<field-validator type="requiredstring">

<param name="trim">true</param>

<message>必須填入名字</message>

</field-validator>

</field>

</validators>

        對于校驗規則檔案的命名采用這個格式:<Action 名字>-validation.xml

        對于使用客服端校驗。我們隻需要為<s:form.../>元素增加validate="true",就可以實作客服端校驗了。但是如果我們希望Struts 2的客服端校驗能夠起作用,那麼我們在進入相應的頁面之前必先經過Struts 2 的核心Filter。

        2、兩種校驗配置風格

        Struts 2提供了兩種方式來配置校驗規則:字段校驗器風格,非字段校驗器風格

        字段校驗器風格:

[html] view plain copy print ?

  1. <field name="被校驗的字段"> 
  2.     <field-validator type="校驗器名"> 
  3.     <!-- 此處需要為不同校驗器指定數量不等的校驗參數--> 
  4.     <param name="參數名">參數值</param> 
  5.     ...... 
  6.     <!-- 校驗失敗後的提示資訊,其中key指定國際化資訊的key--> 
  7.     <message key="I18Nkey">校驗失敗後的提示資訊</message> 
  8.     </field-validator> 
  9.     <!-- 如果該字段需要滿足多個規則,下面可以配置多個校驗器--> 
  10. </field> 

<field name="被校驗的字段">

<field-validator type="校驗器名">

<!-- 此處需要為不同校驗器指定數量不等的校驗參數-->

<param name="參數名">參數值</param>

......

<!-- 校驗失敗後的提示資訊,其中key指定國際化資訊的key-->

<message key="I18Nkey">校驗失敗後的提示資訊</message>

</field-validator>

<!-- 如果該字段需要滿足多個規則,下面可以配置多個校驗器-->

</field>

        非字段校驗器風格:

[html] view plain copy print ?

  1. <validator type="校驗器名"> 
  2.     <param name="fieldname">需要被校驗的字段</param> 
  3.     <!-- 此處需要為不同校驗器指定數量不等的校驗參數--> 
  4.     <param name="參數名">參數值</param> 
  5.     ..... 
  6.     <!-- 校驗失敗後的提示資訊,其中key指定國際化資訊的key--> 
  7.     <message key="I18Nkey">校驗失敗後的提示資訊</message> 
  8. </validator> 

<validator type="校驗器名">

<param name="fieldname">需要被校驗的字段</param>

<!-- 此處需要為不同校驗器指定數量不等的校驗參數-->

<param name="參數名">參數值</param>

.....

<!-- 校驗失敗後的提示資訊,其中key指定國際化資訊的key-->

<message key="I18Nkey">校驗失敗後的提示資訊</message>

</validator>

        3、短路校驗器

        如果我們希望在進行輸入校驗的時候,對于提示資訊我們并不希望一次性全部輸出來,而是根據相應的錯誤,輸出相應的提示資訊。這個時候,我們就可以使用短路校驗器。

        采用短路校驗器,隻需要在<validator.../>元素或<field-validator.../>元素中增加short-circuit="true"即可。

       4、手動完成輸入校驗

        如果需要手動完成輸入校驗,一般是重寫ActionSupport類的validate方法,在重寫這個方法的時候,一旦擔心校驗失敗後,就需要把校驗失敗提示資訊通過addFieldError方法添加到系統的FieldError中。除此之外,不需要做任何額外的處理。

        或者重寫validateXxx方法。其中的Xxx代表了Action對應的處理邏輯方法。其他的和validate方法差不多。不過需要在struts.xml檔案中指定該方法。讓該Action的該方法來處理這個請求。

        Struts 2的輸入校驗需要經過以下幾個步驟:

          1、類型轉換器負責對字元串的請求參數執行類型轉換,并将這些值設定為Action的     屬性值。

          2、在執行類型轉換過程中可能出現異常,如果出現異常,将異常資訊儲存到ActionContext中。conversionError攔截器負責将其封裝到FieldError裡,然後執行第三步;如果轉換過程中沒有異常資訊,則直接進入第三步。

          3、使用Struts 2應用配置的校驗器進行輸入校驗

           4、通過反射調用validateXxx()方法,其中Xxx是即将處理使用者請求的處理邏輯所對應的方法。

           5、調用Action類裡的validate方法。

          6、如果經過上面5步都沒有出現FieldError,将調用Action裡處理使用者請求的處理方法;如果出現了FieldError,系統将會轉入input邏輯視圖所指定的視圖資源。

        流程如下:

struts2知識小結

           七、使用Struts 2控制檔案上傳

           為了能上傳檔案,我們必須将表單的method設定為POST,将enctype設定為multipart-form-data。隻有這樣,浏覽器才會把使用者選擇檔案的二進制資料發送給伺服器。

           1、上傳邏輯控制的Action

           該Action包含兩個屬性:uploadFileName和uploadContentType,這兩個屬性分别用來封裝上傳檔案的檔案名、上傳檔案的檔案類型。

           控制檔案上傳的Action一般需要使用三個屬性來封裝檔案域的資訊:

           類型為File的xxx屬性封裝了該檔案域對應的檔案内容

           類型為String的xxxFileName屬性封裝了該檔案域對應的檔案的檔案名

           類型為String的xxxContentType屬性封裝了該檔案域對應的檔案的檔案類型。

           配置檔案上傳的Action和其他配置Action的檔案差不多。

          2、手動實作檔案過濾

           我們可以通過檔案過濾來實作對上傳者上傳的檔案進行限制。

           如果需要手動實作檔案過濾,需要進行如下步驟:

              1)、在Action中定義一個專用于進行檔案過濾的方法。

              2)為了讓應用程式可以動态配置允許上傳的檔案清單,為該Action增加一個allowTypes屬性,該屬性的值列出了所有允許上傳的檔案類型。

              3)利用Struts 2的輸入校驗來判斷使用者輸入的檔案是否符合要求。

              4)書寫struts.xml配置檔案

           3、攔截器實作檔案過濾

           其實使用攔截器來實作檔案過濾更加友善。畢竟手動實作,書寫的代碼量大了。

           配置fileUpload攔截器時,需要指定兩個參數:allowedTypes、maximumSize

           配置代碼如下:

[html] view plain copy print ?

  1. <interceptor-ref name="fileUpload"> 
  2. <param name="allowedTypes">image/png,image/gif</param> 
  3. <param name="maximumSize">200</param> 
  4. </interceptor-ref> 

<interceptor-ref name="fileUpload">

<param name="allowedTypes">image/png,image/gif</param>

<param name="maximumSize">200</param>

</interceptor-ref>

           八、使用Struts 2控制檔案下載下傳

           相對于檔案上傳,檔案下載下傳簡單些。

           Struts 2的檔案下載下傳的Action與普通的Action有點不同,該Action需要提供一個傳回InputStream流的方法,該輸入流代表了被下載下傳檔案的入口。一旦提供該方法,我們就可以利用該Action來實作檔案下載下傳了。

           配置Action時,最關鍵的一點是需要配置一個類型為stream的結果,該Stream類型的結果将使用檔案下載下傳作文響應。配置stream類型的結果需要指定如下4個屬性:contentType、inputName、contentDisposition、bufferSize。

           注:配置stream類型的結果的時候,因為無需指定實際顯示的實體資源,是以無須指定location屬性,隻需要指定inputName屬性即可,該屬性代表被下載下傳檔案的入口。

           九、Struts 2的攔截器

           Struts 2;攔截器是可插播式的設計:如果我們需要使用某個攔截器,隻需要在配置檔案應用攔截器即可;如果不需要使用該攔截器,隻需要在配置檔案中取消應用該攔截器—不管是否應用某個攔截器,對于Struts 2架構不糊有任何影響。

對于Struts 2而言。它把大部分核心控制器需要完成的工作按功能分開定義,每個攔截器完成一個功能。這樣就可以變得更加靈活。

           1、攔截器的配置    

           攔截器使用<interceptor.../>元素來定義,在配置的攔截器的時候,我們也可以使用<param.../>元素來設定需要傳入的參數。配置如下:

[html] view plain copy print ?

  1. <intercepto name="攔截器名" class="攔截器實作類"> 
  2.     <param name="參數名">參數值</param> 
  3. </intercepto> 

<intercepto name="攔截器名" class="攔截器實作類">

<param name="參數名">參數值</param>

</intercepto>

           <param.../>元素可以出現一次,也可以出現多次,當然也可以不用出現。

           攔截器棧,一個攔截器棧是由多個攔截器組成。但是他和攔截器是統一的,隻不過是由多個攔截器組成的集合。

           配置如下:

[html] view plain copy print ?

  1. <interceptor-stack name="攔截器棧名"> 
  2.     <interceptor-ref name="攔截器一" /> 
  3.     <interceptor-ref name="攔截器二" /> 
  4.     <!-- 在攔截器棧中配置攔截器棧 --> 
  5.     <interceptor-ref name="攔截器棧名" />   
  6. </interceptor-stack> 

<interceptor-stack name="攔截器棧名">

<interceptor-ref name="攔截器一" />

<interceptor-ref name="攔截器二" />

<!-- 在攔截器棧中配置攔截器棧 -->

<interceptor-ref name="攔截器棧名" />

</interceptor-stack>

         2、配置預設攔截器

           一旦為某個包指定了預設攔截器,如果該包中的Action沒有顯示指定攔截器,則預設攔截器将會起作用。但是如果我們為該Action指定了某個攔截器,則預設攔截器就不會起作用了。

           配置預設攔截器使用<default-interceptor-ref.../>元素,該元素作為<package.../>元素的子元素使用,為該包下的所有Action配置預設的攔截器。

           配置<default-interceptor-ref.../>元素時,需要指定一個name屬性,該name屬性是一個已經存在的攔截器。

           配置如下:

[html] view plain copy print ?

  1. <default-interceptor-ref  name="攔截器名或者攔截器棧名"  /> 

<default-interceptor-ref name="攔截器名或者攔截器棧名" />

           同配置攔截器一樣,可以使用<param.../>屬性為該攔截器指定參數值。

           3、使用者自定義攔截器

           如果使用者要開發自己的攔截器,應該要實作Interceptor接口。該接口有三個方法:init()、destroy()、interceptor();其中interceptor方法使使用者需要實作的攔截動作。

           Struts 2還提供一個更加簡單的方式實作攔截器。即使用者繼承AbstractInterceptor類。該類提供了一個init和destroy方法的空實作。如果我們實作的攔截器不需要打開資源,則可以不需要實作這兩個方法。

           當我們實作上面的攔截方法interceptor(ActionInvocation invocation)時,可以通過invocation參數獲得被攔截的Action執行個體,一旦取得了這個Action執行個體,我們就幾乎可以獲得全部的控制器。

           4、使用攔截器

           使用攔截器需要兩個步驟:

                1)、通過<interceptor.../>元素來定義攔截器

               2)、通過<intercepor-ref.../>元素來使用攔截器

           配置檔案如下:

[html] view plain copy print ?

  1. <!-- 配置攔截器 --> 
  2. <interceptor name="myinterceptor" class="com.app.interceptor.SimpleInterceptor"> 
  3.     <!-- 為攔截器指定參數值 --> 
  4.     <param name="name">攔截器一</param> 
  5. </interceptor>  
  6. <action name="simple"> 
  7.     <!-- 引用定義的攔截器 --> 
  8.     <interceptor-ref name="myinterceptor"> 
  9.         <!-- 指定攔截器的參數值 --> 
  10.         <param name="name">攔截器二</param> 
  11.     </interceptor-ref> 
  12. </action> 

<!-- 配置攔截器 -->

<interceptor name="myinterceptor" class="com.app.interceptor.SimpleInterceptor">

<!-- 為攔截器指定參數值 -->

<param name="name">攔截器一</param>

</interceptor>

<action name="simple">

<!-- 引用定義的攔截器 -->

<interceptor-ref name="myinterceptor">

<!-- 指定攔截器的參數值 -->

<param name="name">攔截器二</param>

</interceptor-ref>

</action>

         5、攔截方法的攔截器

           如果我們不需要攔截所有的方法,隻需要攔截器指定的方法,我們可以使用攔截器的方法過濾特性。

           如果使用者自己需要實作攔截器支援方法過濾特性,應該繼承MethodFilterInterceptor類,并且重寫該類的doInterceptor方法定義對Action的攔截邏輯。

           對于方法過濾的配置。它提供了兩個參數:excludeMethod、includeMethods。他們分别指定了不需要攔截的方法和需要的攔截方法。

           如下:

[html] view plain copy print ?

  1. <interceptor-ref name="myinterceptor"> 
  2.         <!-- 指定execute方法不需要攔截 --> 
  3.         <param name="excludeMethods">execute</param> 
  4.         <!-- 指定login方法和regist方法需要攔截 --> 
  5.         <param name="includeMethods">regist,login</param>    
  6. </interceptor-ref> 

<interceptor-ref name="myinterceptor">

<!-- 指定execute方法不需要攔截 -->

<param name="excludeMethods">execute</param>

<!-- 指定login方法和regist方法需要攔截 -->

<param name="includeMethods">regist,login</param>

</interceptor-ref>

           注:如果excludeMethods參數和includeMethods參數同時指定一個方法名,則攔截器會攔截該方法。

           6、攔截器的執行順序

           一般情況下,先配置的攔截器會先獲得執行的機會。但是有時候會不有出入。

           對于攔截器的執行順序,總結下面一句話:在Action的控制方法執行之前,位于攔截器鍊前面的攔截器會先執行,在Action的控制方法執行之後,位于攔截器鍊後面的攔截器會先發生作用。一、Struts 2應用的開發步驟

         1、首先要先下載下傳Struts 2的jar包,将必須的類庫放入到Web應用下的WEB-INF/lib路徑下。

         2、配置web應用的web.xml配置檔案,配置Struts 2的核心Filter

         3、定義處理使用者請求的Action類

         4、配置Action

         5、配置處理結果和實體試圖資源之間的對應關系

         上面的配置比較簡單,但是這是Struts 2最基本配置。

         三、Struts 2的異常處理

         我們在實作execute方法的時候,該方法是将異常直接抛出,交給Struts 2架構來處理。                

         這就意味着,我們在處理使用者請求的時候,可以不需要對異常進行處理,直接抛出交給Strust 2處理,Struts 2接收到Action抛出的異常之後,将會根據struts.xml檔案配置的異常映射關系,轉入到指定的視圖資源。

         Strut 2的異常處理機制是通過在struts.xml檔案中配置<exception-mapping.../>元素完成的。配置該元素時,需要指定如下兩個屬性:exception、result。

         如下:

[html] view plain copy print ?

  1. <!-- 定義全局異常映射 --> 
  2.     <global-exception-mappings> 
  3.         <!-- 當Action中遇到SQLException異常時,系統将會轉入到name問sql的結果中 --> 
  4.         <exception-mapping result="sql" exception="java.sql.SQLException"></exception-mapping> 
  5.         <!-- 當Action中遇到Exception異常時,系統将會轉入到name為root的結果中 --> 
  6.         <exception-mapping result="root" exception="java.lang.Exception"></exception-mapping> 
  7.     </global-exception-mappings> 

<!-- 定義全局異常映射 -->

<global-exception-mappings>

<!-- 當Action中遇到SQLException異常時,系統将會轉入到name問sql的結果中 -->

<exception-mapping result="sql" exception="java.sql.SQLException"></exception-mapping>

<!-- 當Action中遇到Exception異常時,系統将會轉入到name為root的結果中 -->

<exception-mapping result="root" exception="java.lang.Exception"></exception-mapping>

</global-exception-mappings>

        對于異常的輸出,我們采用如下方式:

[html] view plain copy print ?

  1. <s:property value="exception"/> 

<s:property value="exception"/>

       *  四、使用Struts 2國際化

        Strut 2的國際化是建立在java國際化的基礎上的。對于Struts 2的國際化我們一般采用加載全局的國際化資源檔案,加載全局的國際化資源檔案的方式是通過配置常量來實作的。在檔案中配置我們隻需要配置struts.custom.i18n.resoutces常量即可。

        配置struts.custom.i18n.resoutces常量時,該常量的值為全局國際化資源檔案的baseName。一旦指定了全局的國際化資源檔案,既可以實作程式的國際化。

        在struts.xml檔案中我們需要配置如下代碼:

[html] view plain copy print ?

  1. <!--指定Struts 2國際化資源檔案的baseName為messageResource --> 
  2. <constant name="struts.custom.i18n.resoutces" value="messageResource" /> 

<!--指定Struts 2國際化資源檔案的baseName為messageResource -->

<constant name="struts.custom.i18n.resoutces" value="messageResource" />

        對于國際化資源檔案,我們一般采用鍵值對的properties檔案。為了在頁面中輸出國際化資源,我們可以使用Struts 2的<s:text.../>标簽,該标簽的name屬性,指定了國際化資源檔案中的key。

         五、Strut 2的類型轉換

        Struts 2的類型轉換可以基于ONGL表達式。隻要我們把Http參數的命名為合法的ONGL表達式,就可以充分的利用Struts 2的類型轉換機制。

        對于Struts 2内建的類型轉換,我們無需理會,不需要做任何特殊的處理。

        自定義類型轉換

        對于使用者自定義類型轉換器,使用者必須要實作TypeConverter接口。實作自定義類型轉換器需要重寫該方法的convertValue方法。

        該方法是雙向的。可以将字元串轉換成複合類型,也可以将複合類型轉換為字元串。該方法主要是通過toType參數來判斷轉換的方向。

        其實基于Struts 2的自定義類型轉換器,我們可以有更簡單的方法實作。Struts 2提供了一個StrutsTypeString抽象類。該抽象類提供了兩個方法:convertFromString和convertToString。通過實作這個兩個方法就可以實作自定義類型轉換了。

        如下:

[java] view plain copy print ?

  1. public class UserConverter extends StrutsTypeConverter{ 
  2.        //實作将字元串類型轉換為複合類型的方法 
  3.         public object converterFromString(Map context,String[] values,Class toClass){ 
  4.              .............................. 
  5.        } 
  6.       //實作将複合類型轉換為字元串類型的方法 
  7.         public String converterToString(Map context,Object o){ 
  8.              .................... 
  9.        } 

public class UserConverter extends StrutsTypeConverter{

//實作将字元串類型轉換為複合類型的方法

public object converterFromString(Map context,String[] values,Class toClass){

..............................

}

//實作将複合類型轉換為字元串類型的方法

public String converterToString(Map context,Object o){

....................

}

}

        完成了自定義類型轉換器後,還要将類型轉換器注冊到Web應用中去:

        局部類型轉換器:

        <proName>=<ConverterClass>

        <proName>:需要進行類型轉換的屬性

        <ConverterClass>:類型轉換器的實作類

        如下:

[html] view plain copy print ?

  1. user = com.app.converter.UserConverter 

user = com.app.converter.UserConverter

       * 全局類型轉換器:

        <propType>=<ConvertClass>

        <propType>:需要進行類型轉換的類型

        <ConvertClass>需要進行類型轉換的實作類

        如下:

[html] view plain copy print ?

  1. comcom.app.domain.User = com.app.converter.UserConverter 

com.app.domain.User = com.app.converter.UserConverter

        六、使用Struts 2的輸入校驗

        Struts 2提供了基于驗證架構的輸入校驗,在這種校驗方式下,所有的輸入校驗隻需要編寫簡單的配置檔案,Struts 2的驗證架構将會負責進行伺服器校驗和客服端校驗。    

        1、編寫校驗規則檔案

        校驗規則檔案的根元素是<validator.../>元素,<validator.../>元素可以包含多個<field../>或<validator.../>,他們都用于配置校驗規則。

        配置片段:

[html] view plain copy print ?

  1. <validators> 
  2.     <!-- 校驗Action的name屬性 --> 
  3.     <field name="name"> 
  4.         <!-- 指定name屬性必須滿足必填規則 --> 
  5.         <field-validator type="requiredstring"> 
  6.             <param name="trim">true</param> 
  7.             <message>必須填入名字</message> 
  8.         </field-validator> 
  9.     </field> 
  10. </validators> 

<validators>

<!-- 校驗Action的name屬性 -->

<field name="name">

<!-- 指定name屬性必須滿足必填規則 -->

<field-validator type="requiredstring">

<param name="trim">true</param>

<message>必須填入名字</message>

</field-validator>

</field>

</validators>

        對于校驗規則檔案的命名采用這個格式:<Action 名字>-validation.xml

        對于使用客服端校驗。我們隻需要為<s:form.../>元素增加validate="true",就可以實作客服端校驗了。但是如果我們希望Struts 2的客服端校驗能夠起作用,那麼我們在進入相應的頁面之前必先經過Struts 2 的核心Filter。

        2、兩種校驗配置風格

        Struts 2提供了兩種方式來配置校驗規則:字段校驗器風格,非字段校驗器風格

        字段校驗器風格:

[html] view plain copy print ?

  1. <field name="被校驗的字段"> 
  2.     <field-validator type="校驗器名"> 
  3.     <!-- 此處需要為不同校驗器指定數量不等的校驗參數--> 
  4.     <param name="參數名">參數值</param> 
  5.     ...... 
  6.     <!-- 校驗失敗後的提示資訊,其中key指定國際化資訊的key--> 
  7.     <message key="I18Nkey">校驗失敗後的提示資訊</message> 
  8.     </field-validator> 
  9.     <!-- 如果該字段需要滿足多個規則,下面可以配置多個校驗器--> 
  10. </field> 

<field name="被校驗的字段">

<field-validator type="校驗器名">

<!-- 此處需要為不同校驗器指定數量不等的校驗參數-->

<param name="參數名">參數值</param>

......

<!-- 校驗失敗後的提示資訊,其中key指定國際化資訊的key-->

<message key="I18Nkey">校驗失敗後的提示資訊</message>

</field-validator>

<!-- 如果該字段需要滿足多個規則,下面可以配置多個校驗器-->

</field>

        非字段校驗器風格:

[html] view plain copy print ?

  1. <validator type="校驗器名"> 
  2.     <param name="fieldname">需要被校驗的字段</param> 
  3.     <!-- 此處需要為不同校驗器指定數量不等的校驗參數--> 
  4.     <param name="參數名">參數值</param> 
  5.     ..... 
  6.     <!-- 校驗失敗後的提示資訊,其中key指定國際化資訊的key--> 
  7.     <message key="I18Nkey">校驗失敗後的提示資訊</message> 
  8. </validator> 

<validator type="校驗器名">

<param name="fieldname">需要被校驗的字段</param>

<!-- 此處需要為不同校驗器指定數量不等的校驗參數-->

<param name="參數名">參數值</param>

.....

<!-- 校驗失敗後的提示資訊,其中key指定國際化資訊的key-->

<message key="I18Nkey">校驗失敗後的提示資訊</message>

</validator>

        3、短路校驗器

        如果我們希望在進行輸入校驗的時候,對于提示資訊我們并不希望一次性全部輸出來,而是根據相應的錯誤,輸出相應的提示資訊。這個時候,我們就可以使用短路校驗器。

        采用短路校驗器,隻需要在<validator.../>元素或<field-validator.../>元素中增加short-circuit="true"即可。

       4、手動完成輸入校驗

        如果需要手動完成輸入校驗,一般是重寫ActionSupport類的validate方法,在重寫這個方法的時候,一旦擔心校驗失敗後,就需要把校驗失敗提示資訊通過addFieldError方法添加到系統的FieldError中。除此之外,不需要做任何額外的處理。

        或者重寫validateXxx方法。其中的Xxx代表了Action對應的處理邏輯方法。其他的和validate方法差不多。不過需要在struts.xml檔案中指定該方法。讓該Action的該方法來處理這個請求。

        Struts 2的輸入校驗需要經過以下幾個步驟:

          1、類型轉換器負責對字元串的請求參數執行類型轉換,并将這些值設定為Action的     屬性值。

          2、在執行類型轉換過程中可能出現異常,如果出現異常,将異常資訊儲存到ActionContext中。conversionError攔截器負責将其封裝到FieldError裡,然後執行第三步;如果轉換過程中沒有異常資訊,則直接進入第三步。

          3、使用Struts 2應用配置的校驗器進行輸入校驗

           4、通過反射調用validateXxx()方法,其中Xxx是即将處理使用者請求的處理邏輯所對應的方法。

           5、調用Action類裡的validate方法。

          6、如果經過上面5步都沒有出現FieldError,将調用Action裡處理使用者請求的處理方法;如果出現了FieldError,系統将會轉入input邏輯視圖所指定的視圖資源。

        流程如下:

struts2知識小結

           七、使用Struts 2控制檔案上傳

           為了能上傳檔案,我們必須将表單的method設定為POST,将enctype設定為multipart-form-data。隻有這樣,浏覽器才會把使用者選擇檔案的二進制資料發送給伺服器。

           1、上傳邏輯控制的Action

           該Action包含兩個屬性:uploadFileName和uploadContentType,這兩個屬性分别用來封裝上傳檔案的檔案名、上傳檔案的檔案類型。

           控制檔案上傳的Action一般需要使用三個屬性來封裝檔案域的資訊:

           類型為File的xxx屬性封裝了該檔案域對應的檔案内容

           類型為String的xxxFileName屬性封裝了該檔案域對應的檔案的檔案名

           類型為String的xxxContentType屬性封裝了該檔案域對應的檔案的檔案類型。

           配置檔案上傳的Action和其他配置Action的檔案差不多。

          2、手動實作檔案過濾

           我們可以通過檔案過濾來實作對上傳者上傳的檔案進行限制。

           如果需要手動實作檔案過濾,需要進行如下步驟:

              1)、在Action中定義一個專用于進行檔案過濾的方法。

              2)為了讓應用程式可以動态配置允許上傳的檔案清單,為該Action增加一個allowTypes屬性,該屬性的值列出了所有允許上傳的檔案類型。

              3)利用Struts 2的輸入校驗來判斷使用者輸入的檔案是否符合要求。

              4)書寫struts.xml配置檔案

           3、攔截器實作檔案過濾

           其實使用攔截器來實作檔案過濾更加友善。畢竟手動實作,書寫的代碼量大了。

           配置fileUpload攔截器時,需要指定兩個參數:allowedTypes、maximumSize

           配置代碼如下:

[html] view plain copy print ?

  1. <interceptor-ref name="fileUpload"> 
  2. <param name="allowedTypes">image/png,image/gif</param> 
  3. <param name="maximumSize">200</param> 
  4. </interceptor-ref> 

<interceptor-ref name="fileUpload">

<param name="allowedTypes">image/png,image/gif</param>

<param name="maximumSize">200</param>

</interceptor-ref>

           八、使用Struts 2控制檔案下載下傳

           相對于檔案上傳,檔案下載下傳簡單些。

           Struts 2的檔案下載下傳的Action與普通的Action有點不同,該Action需要提供一個傳回InputStream流的方法,該輸入流代表了被下載下傳檔案的入口。一旦提供該方法,我們就可以利用該Action來實作檔案下載下傳了。

           配置Action時,最關鍵的一點是需要配置一個類型為stream的結果,該Stream類型的結果将使用檔案下載下傳作文響應。配置stream類型的結果需要指定如下4個屬性:contentType、inputName、contentDisposition、bufferSize。

           注:配置stream類型的結果的時候,因為無需指定實際顯示的實體資源,是以無須指定location屬性,隻需要指定inputName屬性即可,該屬性代表被下載下傳檔案的入口。

           九、Struts 2的攔截器

           Struts 2;攔截器是可插播式的設計:如果我們需要使用某個攔截器,隻需要在配置檔案應用攔截器即可;如果不需要使用該攔截器,隻需要在配置檔案中取消應用該攔截器—不管是否應用某個攔截器,對于Struts 2架構不糊有任何影響。

對于Struts 2而言。它把大部分核心控制器需要完成的工作按功能分開定義,每個攔截器完成一個功能。這樣就可以變得更加靈活。

           1、攔截器的配置    

           攔截器使用<interceptor.../>元素來定義,在配置的攔截器的時候,我們也可以使用<param.../>元素來設定需要傳入的參數。配置如下:

[html] view plain copy print ?

  1. <intercepto name="攔截器名" class="攔截器實作類"> 
  2.     <param name="參數名">參數值</param> 
  3. </intercepto> 

<intercepto name="攔截器名" class="攔截器實作類">

<param name="參數名">參數值</param>

</intercepto>

           <param.../>元素可以出現一次,也可以出現多次,當然也可以不用出現。

           攔截器棧,一個攔截器棧是由多個攔截器組成。但是他和攔截器是統一的,隻不過是由多個攔截器組成的集合。

           配置如下:

[html] view plain copy print ?

  1. <interceptor-stack name="攔截器棧名"> 
  2.     <interceptor-ref name="攔截器一" /> 
  3.     <interceptor-ref name="攔截器二" /> 
  4.     <!-- 在攔截器棧中配置攔截器棧 --> 
  5.     <interceptor-ref name="攔截器棧名" />   
  6. </interceptor-stack> 

<interceptor-stack name="攔截器棧名">

<interceptor-ref name="攔截器一" />

<interceptor-ref name="攔截器二" />

<!-- 在攔截器棧中配置攔截器棧 -->

<interceptor-ref name="攔截器棧名" />

</interceptor-stack>

         2、配置預設攔截器

           一旦為某個包指定了預設攔截器,如果該包中的Action沒有顯示指定攔截器,則預設攔截器将會起作用。但是如果我們為該Action指定了某個攔截器,則預設攔截器就不會起作用了。

           配置預設攔截器使用<default-interceptor-ref.../>元素,該元素作為<package.../>元素的子元素使用,為該包下的所有Action配置預設的攔截器。

           配置<default-interceptor-ref.../>元素時,需要指定一個name屬性,該name屬性是一個已經存在的攔截器。

           配置如下:

[html] view plain copy print ?

  1. <default-interceptor-ref  name="攔截器名或者攔截器棧名"  /> 

<default-interceptor-ref name="攔截器名或者攔截器棧名" />

           同配置攔截器一樣,可以使用<param.../>屬性為該攔截器指定參數值。

           3、使用者自定義攔截器

           如果使用者要開發自己的攔截器,應該要實作Interceptor接口。該接口有三個方法:init()、destroy()、interceptor();其中interceptor方法使使用者需要實作的攔截動作。

           Struts 2還提供一個更加簡單的方式實作攔截器。即使用者繼承AbstractInterceptor類。該類提供了一個init和destroy方法的空實作。如果我們實作的攔截器不需要打開資源,則可以不需要實作這兩個方法。

           當我們實作上面的攔截方法interceptor(ActionInvocation invocation)時,可以通過invocation參數獲得被攔截的Action執行個體,一旦取得了這個Action執行個體,我們就幾乎可以獲得全部的控制器。

           4、使用攔截器

           使用攔截器需要兩個步驟:

                1)、通過<interceptor.../>元素來定義攔截器

               2)、通過<intercepor-ref.../>元素來使用攔截器

           配置檔案如下:

[html] view plain copy print ?

  1. <!-- 配置攔截器 --> 
  2. <interceptor name="myinterceptor" class="com.app.interceptor.SimpleInterceptor"> 
  3.     <!-- 為攔截器指定參數值 --> 
  4.     <param name="name">攔截器一</param> 
  5. </interceptor>  
  6. <action name="simple"> 
  7.     <!-- 引用定義的攔截器 --> 
  8.     <interceptor-ref name="myinterceptor"> 
  9.         <!-- 指定攔截器的參數值 --> 
  10.         <param name="name">攔截器二</param> 
  11.     </interceptor-ref> 
  12. </action> 

<!-- 配置攔截器 -->

<interceptor name="myinterceptor" class="com.app.interceptor.SimpleInterceptor">

<!-- 為攔截器指定參數值 -->

<param name="name">攔截器一</param>

</interceptor>

<action name="simple">

<!-- 引用定義的攔截器 -->

<interceptor-ref name="myinterceptor">

<!-- 指定攔截器的參數值 -->

<param name="name">攔截器二</param>

</interceptor-ref>

</action>

         5、攔截方法的攔截器

           如果我們不需要攔截所有的方法,隻需要攔截器指定的方法,我們可以使用攔截器的方法過濾特性。

           如果使用者自己需要實作攔截器支援方法過濾特性,應該繼承MethodFilterInterceptor類,并且重寫該類的doInterceptor方法定義對Action的攔截邏輯。

           對于方法過濾的配置。它提供了兩個參數:excludeMethod、includeMethods。他們分别指定了不需要攔截的方法和需要的攔截方法。

           如下:

[html] view plain copy print ?

  1. <interceptor-ref name="myinterceptor"> 
  2.         <!-- 指定execute方法不需要攔截 --> 
  3.         <param name="excludeMethods">execute</param> 
  4.         <!-- 指定login方法和regist方法需要攔截 --> 
  5.         <param name="includeMethods">regist,login</param>    
  6. </interceptor-ref> 

<interceptor-ref name="myinterceptor">

<!-- 指定execute方法不需要攔截 -->

<param name="excludeMethods">execute</param>

<!-- 指定login方法和regist方法需要攔截 -->

<param name="includeMethods">regist,login</param>

</interceptor-ref>

           注:如果excludeMethods參數和includeMethods參數同時指定一個方法名,則攔截器會攔截該方法。

           6、攔截器的執行順序

           一般情況下,先配置的攔截器會先獲得執行的機會。但是有時候會不有出入。

           對于攔截器的執行順序,總結下面一句話:在Action的控制方法執行之前,位于攔截器鍊前面的攔截器會先執行,在Action的控制方法執行之後,位于攔截器鍊後面的攔截器會先發生作用。

繼續閱讀