在web應用程序中我們都是使用部署描述符來初始化一些資源如servlet、過濾器、監聽器等等,這個部署描述符就是那廣爲人知的web.xml了。同樣的,框架也使用一個配置文件來初始化它自己的資源,這些資源主要包括:
1.攔截器(Interceptor):對請求進行預處理和後加工;
2.Action Classes:負責調用商業邏輯和數據訪問層;
3.Results:負責返回視圖(view),如JSP頁面等等;
只有單獨一個配置文件(struts.properties)來控制應用程序的運行時行爲,在 運行前,配置是通過一個或多個xml文件來定義的,包括那個默認的struts.xml文件。可供配置的元素有:package、namespace、include、action、result、interceptor、exception等。這些元素按照功能的不同可以分爲:管理層元素(Administrative Elements)、請求處理元素(Request Handling)、錯誤處理元素(Error Handling)。下面對其分別進行介紹。
1.配置Bean元素
通常框架會使用它自己的“依賴注入”(dependency injection)容器,這個容器會裝載那些關鍵的框架對象,這樣框架的任何部分都能夠 以一種標準、一致的方式被取代、擴展或者除去 (這段話的意思我不是很明白) 。尤其是插件,可以通過這種方式對框架進行擴展,使它能夠支持第三方的類庫如Spring、SiteMesh。通常情況下,大多數應用都不需要配置它。
Bean元素的所有屬性信息如小表所示:
表1:bean元素屬性信息一欄表
屬性名稱 |
是否必須 |
描述 |
class |
是 |
bean的類名 |
type |
否 |
bean實現的主要接口 |
name |
否 |
bean的名字,必須唯一 |
scope |
否 |
bean的作用域,是default,singleton,request,session,thread中的一個 |
static |
否 |
是否注入靜態方法,如果指定了type,static就不能爲true |
optional |
否 |
Bean是否可選 |
這裏有一點應說明,關於bean的name屬性的唯一性問題,它是指不允許兩個bean的type屬性相同並且name屬性也相同,也就是說在所有type相同的bean中,必須確保name屬性的唯一性。這點我們在struts-default.xml中看到,有好幾個bean的name都是”struts”,但是它們的type屬性不同。bean的主要功能有兩點
● 被框架容器創建然後注入到內部的框架對象中去
● 將值注入它的靜態方法(這個我還不是很能理解)
第一個作用可以稱爲對象注入,它通常要用到bean的type屬性,告訴容器這個對象
實現了哪個接口;第二個作用可以稱爲值注入,它有利於那些不是由容器創建的對象檢索框架常量。使用值注入的對象必須定義”static”屬性。(不知哪有例子可以看一下,^_^)
下面給出一個簡單的bean元素的例子,從struts-default.xml中摘錄出來的:
<bean type="com.opensymphony.xwork2.ObjectFactory"
name="struts" class="org.apache.struts2.impl.StrutsObjectFactory" />
就我個人的理解,配置一個bean的作用就相當於告訴struts框架,在它啓動的時候
由容器預先創建好這樣一個對象,以供別的對象調用,就像spring中的IoC容器一樣。
2.常量配置
我們可以通過定義一些能夠改變框架和插件行爲的關鍵設置來定製我們struts應用程序,而這些設置就是常量。常量扮演了兩個關鍵的角色:首先它們被用來覆蓋一些原有的默認設置,例如上傳文件的最大容量、框架是否處於開發模式等等;其次,常量還用來指定在一個類型(type)的多個實現中,哪個bean應該被選中。
常量可以定義在多個文件中,默認情況下我們按照下面的順序來尋找常量,後面的將覆蓋前面的設置:
● struts-default.xml
● struts-plugin.xml
● struts.xml
● struts.properties
● web.xml
前3個xml文件的格式是一樣的,因爲它們使用同一個DTD文件,在xml文件中Constant元素有兩個必須的屬性:name和value;在struts.properties文件中,每一個entry都被視爲一個常量;在web.xml文件中FilterDispatcher的初始化參數被載入爲常量。下面分別給出3中常量形式的例子。
struts.xml文件中常量
struts.properties文件中常量
web.xml文件中常量
<filter>
<filter-name>struts</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-clas s>
<init-param>
<param-name>struts.devMode</param-name>
<param-value>true</param-value>
</init-param>
</filter>
</web-app>
3.package配置
packages爲我們提供了一種將action,result,攔截器聚集成一個邏輯單元的簡單方式。package元素的屬性列表如下圖所示:
表2:package元素屬性一覽表
屬性名 |
是否必須 |
描述 |
name |
是 |
package的唯一標識,不允許同名 |
extends |
否 |
繼承它所擴張包的行爲 |
namespace |
否 |
見後面的namespace配置 |
abstract |
否 |
聲明包爲抽象包,無需配置任何action |
上表中的extends屬性允許一個包繼承前面一個或多個包的配置,包括所有的攔截器、攔截器棧和action配置。要注意的是,配置文件是按照從上往下的順序被處理的,也就是說如果一個package繼承了另外一個package,那麼它所繼承的package必須要在它之前被定義。下面給出了一個package的樣本:
關於這個extends屬性我做了一下測試,我在package中配置了這個的一個action
<action name="HelloWorld" class="tutorial.HelloWorld" >
<result>/HelloWorld.jsp</result>
</action>
測試情況如下
◆ 不給package元素設置extends屬性,此時應用加載失敗,後臺提示如下錯誤:
Error building results for action HelloWorld in namespace
◆ 給package元素設置一個extends屬性,但是它指向一個並不存在的包,如下所示:
Extends=”121212”,此時應用加載成功,但是後臺會提示Unable to find parent
packages 1212121。此時如果調用HelloWorld.action,系統會報如下錯誤:
There is no Action mapped for namespace / and action name HelloWorld
◆ 給package元素設置一個extends屬性,它指向一個已存在的包,如果此包沒有設置
extends屬性那麼就會出現第一種情況的錯誤。
總之,我們定義一個package的時候,最好是將它的extends屬性設置爲”struts-default”,
如果不是”struts-default”,那麼我們要確保它的家族鏈上有一個包的extends屬性爲”struts-default”。所謂家族鏈就是說要追溯它的父包,祖父包,直至它的一世組包,不過通常狀況下不會有這麼多代咯,我們都會直接把package的extends屬性設置爲”struts-default”。