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 ?
- <package name="mypackage" extends="struts-default">
- .....................
- </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 ?
- <package name="lee">
- <action name="login" class="com.app.action.LoginAction"></action>
- </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 ?
- <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 ?
- <action name="login">
- <!-- 配置預設結果,省略type屬性,預設dispatcher -->
- <result>/welcome.jsp</result>
- </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 ?
- <!-- 定義全局異常映射 -->
- <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>
<!-- 定義全局異常映射 -->
<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 ?
- <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 ?
- <!--指定Struts 2國際化資源檔案的baseName為messageResource -->
- <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 ?
- public class UserConverter extends StrutsTypeConverter{
- //實作将字元串類型轉換為複合類型的方法
- public object converterFromString(Map context,String[] values,Class toClass){
- ..............................
- }
- //實作将複合類型轉換為字元串類型的方法
- public String converterToString(Map context,Object o){
- ....................
- }
- }
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 ?
- user = com.app.converter.UserConverter
user = com.app.converter.UserConverter
全局類型轉換器:
<propType>=<ConvertClass>
<propType>:需要進行類型轉換的類型
<ConvertClass>需要進行類型轉換的實作類
如下:
[html] view plain copy print ?
- 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 ?
- <validators>
- <!-- 校驗Action的name屬性 -->
- <field name="name">
- <!-- 指定name屬性必須滿足必填規則 -->
- <field-validator type="requiredstring">
- <param name="trim">true</param>
- <message>必須填入名字</message>
- </field-validator>
- </field>
- </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 ?
- <field name="被校驗的字段">
- <field-validator type="校驗器名">
- <!-- 此處需要為不同校驗器指定數量不等的校驗參數-->
- <param name="參數名">參數值</param>
- ......
- <!-- 校驗失敗後的提示資訊,其中key指定國際化資訊的key-->
- <message key="I18Nkey">校驗失敗後的提示資訊</message>
- </field-validator>
- <!-- 如果該字段需要滿足多個規則,下面可以配置多個校驗器-->
- </field>
<field name="被校驗的字段">
<field-validator type="校驗器名">
<!-- 此處需要為不同校驗器指定數量不等的校驗參數-->
<param name="參數名">參數值</param>
......
<!-- 校驗失敗後的提示資訊,其中key指定國際化資訊的key-->
<message key="I18Nkey">校驗失敗後的提示資訊</message>
</field-validator>
<!-- 如果該字段需要滿足多個規則,下面可以配置多個校驗器-->
</field>
非字段校驗器風格:
[html] view plain copy print ?
- <validator type="校驗器名">
- <param name="fieldname">需要被校驗的字段</param>
- <!-- 此處需要為不同校驗器指定數量不等的校驗參數-->
- <param name="參數名">參數值</param>
- .....
- <!-- 校驗失敗後的提示資訊,其中key指定國際化資訊的key-->
- <message key="I18Nkey">校驗失敗後的提示資訊</message>
- </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邏輯視圖所指定的視圖資源。
流程如下:

七、使用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 ?
- <interceptor-ref name="fileUpload">
- <param name="allowedTypes">image/png,image/gif</param>
- <param name="maximumSize">200</param>
- </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 ?
- <intercepto name="攔截器名" class="攔截器實作類">
- <param name="參數名">參數值</param>
- </intercepto>
<intercepto name="攔截器名" class="攔截器實作類">
<param name="參數名">參數值</param>
</intercepto>
<param.../>元素可以出現一次,也可以出現多次,當然也可以不用出現。
攔截器棧,一個攔截器棧是由多個攔截器組成。但是他和攔截器是統一的,隻不過是由多個攔截器組成的集合。
配置如下:
[html] view plain copy print ?
- <interceptor-stack name="攔截器棧名">
- <interceptor-ref name="攔截器一" />
- <interceptor-ref name="攔截器二" />
- <!-- 在攔截器棧中配置攔截器棧 -->
- <interceptor-ref name="攔截器棧名" />
- </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 ?
- <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 ?
- <!-- 配置攔截器 -->
- <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>
<!-- 配置攔截器 -->
<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 ?
- <interceptor-ref name="myinterceptor">
- <!-- 指定execute方法不需要攔截 -->
- <param name="excludeMethods">execute</param>
- <!-- 指定login方法和regist方法需要攔截 -->
- <param name="includeMethods">regist,login</param>
- </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 ?
- <!-- 定義全局異常映射 -->
- <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>
<!-- 定義全局異常映射 -->
<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 ?
- <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 ?
- <!--指定Struts 2國際化資源檔案的baseName為messageResource -->
- <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 ?
- public class UserConverter extends StrutsTypeConverter{
- //實作将字元串類型轉換為複合類型的方法
- public object converterFromString(Map context,String[] values,Class toClass){
- ..............................
- }
- //實作将複合類型轉換為字元串類型的方法
- public String converterToString(Map context,Object o){
- ....................
- }
- }
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 ?
- user = com.app.converter.UserConverter
user = com.app.converter.UserConverter
* 全局類型轉換器:
<propType>=<ConvertClass>
<propType>:需要進行類型轉換的類型
<ConvertClass>需要進行類型轉換的實作類
如下:
[html] view plain copy print ?
- 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 ?
- <validators>
- <!-- 校驗Action的name屬性 -->
- <field name="name">
- <!-- 指定name屬性必須滿足必填規則 -->
- <field-validator type="requiredstring">
- <param name="trim">true</param>
- <message>必須填入名字</message>
- </field-validator>
- </field>
- </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 ?
- <field name="被校驗的字段">
- <field-validator type="校驗器名">
- <!-- 此處需要為不同校驗器指定數量不等的校驗參數-->
- <param name="參數名">參數值</param>
- ......
- <!-- 校驗失敗後的提示資訊,其中key指定國際化資訊的key-->
- <message key="I18Nkey">校驗失敗後的提示資訊</message>
- </field-validator>
- <!-- 如果該字段需要滿足多個規則,下面可以配置多個校驗器-->
- </field>
<field name="被校驗的字段">
<field-validator type="校驗器名">
<!-- 此處需要為不同校驗器指定數量不等的校驗參數-->
<param name="參數名">參數值</param>
......
<!-- 校驗失敗後的提示資訊,其中key指定國際化資訊的key-->
<message key="I18Nkey">校驗失敗後的提示資訊</message>
</field-validator>
<!-- 如果該字段需要滿足多個規則,下面可以配置多個校驗器-->
</field>
非字段校驗器風格:
[html] view plain copy print ?
- <validator type="校驗器名">
- <param name="fieldname">需要被校驗的字段</param>
- <!-- 此處需要為不同校驗器指定數量不等的校驗參數-->
- <param name="參數名">參數值</param>
- .....
- <!-- 校驗失敗後的提示資訊,其中key指定國際化資訊的key-->
- <message key="I18Nkey">校驗失敗後的提示資訊</message>
- </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邏輯視圖所指定的視圖資源。
流程如下:

七、使用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 ?
- <interceptor-ref name="fileUpload">
- <param name="allowedTypes">image/png,image/gif</param>
- <param name="maximumSize">200</param>
- </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 ?
- <intercepto name="攔截器名" class="攔截器實作類">
- <param name="參數名">參數值</param>
- </intercepto>
<intercepto name="攔截器名" class="攔截器實作類">
<param name="參數名">參數值</param>
</intercepto>
<param.../>元素可以出現一次,也可以出現多次,當然也可以不用出現。
攔截器棧,一個攔截器棧是由多個攔截器組成。但是他和攔截器是統一的,隻不過是由多個攔截器組成的集合。
配置如下:
[html] view plain copy print ?
- <interceptor-stack name="攔截器棧名">
- <interceptor-ref name="攔截器一" />
- <interceptor-ref name="攔截器二" />
- <!-- 在攔截器棧中配置攔截器棧 -->
- <interceptor-ref name="攔截器棧名" />
- </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 ?
- <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 ?
- <!-- 配置攔截器 -->
- <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>
<!-- 配置攔截器 -->
<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 ?
- <interceptor-ref name="myinterceptor">
- <!-- 指定execute方法不需要攔截 -->
- <param name="excludeMethods">execute</param>
- <!-- 指定login方法和regist方法需要攔截 -->
- <param name="includeMethods">regist,login</param>
- </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的控制方法執行之後,位于攔截器鍊後面的攔截器會先發生作用。