在Struts架構中,一般使用一種名爲ActionForm的系統狀態Bean,來實現應用系統的非持久性數據存儲和維護功能.具體來講,這種類型的對象主要用於保存用戶請求表單中的數據,並可保持其狀態的連續性,即在不一樣的頁面間傳遞這些數據. ActionForm Bean的運行處理過程以下:apache
控制器ActionServlet接收到一個客戶端請求後,會將該請求委託給一個RequestProcessor對象進行處理.該對象是遵守配置文件struts-config.xml中與該請求匹配的<action>子元素的約定對該請求進行處理的,首先依據<action>元素的name屬性在規定的範圍(「request」或」session」)內查找指定的 ActionForm Bean,若是找不到則自動建立一個新的Bean實例. RequestProcessor隨後重置該表單Bean的狀態,即便用請求表單中的數據自動填充其相應屬性.而後該Bean被做爲參數傳遞給相應的處理器Action對象的execute()方法開始後續的處理過程.session
下面咱們將經過各類不一樣的Action和ActionForm組合來更清楚地瞭解它們的運行機理以及它們的不一樣組合帶來的效果.
一. 完整的action架構
<action path="/aFullAction"
type="somePackage.someActionClass">
name="someForm"
input="someJSP.jsp"
<forward name="successful" path="someJSP.jsp"/>
<forward name="failed" path="someOtherJSP.jsp"/>
</action>app
首先,Struts的ActionServlet接收到一個請求,而後根據struts-config.xml的配置定位到相應的mapping(映射);接下來若是form的範圍是request或者在定義的範圍中找不到這個form,建立一個新的form實例;取得form實例之後,調用其 reset()方法,而後將表單中的參數放入form,若是validate屬性不爲false,調用validate()方法;若是 validate()返回非空的ActionErrors,將會被轉到input屬性指定的URI,若是返回空的ActionErrors,那麼執行 Action的execute()方法,根據返回的ActionForward肯定目標URI。
這樣作的效果是:execute()僅當validate()成功之後才執行;input屬性指定的是一個URI。
二. 僅有Form的actionjsp
<action path="/aFormOnlyAction"
type="org.apache.struts.actions.ForwardAction"
name="someForm"
input="someJSP.jsp"
parameter="someOtherJSP.jsp"
/>
首先,Struts會在定義的scope搜尋someForm,若是找到則重用,若是找不到則新建一個實例;取得form實例之後,調用其reset() 方法,而後將表單中的參數放入form,若是validate屬性不爲false,調用validate()方法;若是validate()返回非空的 ActionErrors,將會被轉到input屬性指定的URI,若是返回空的ActionErrors,那麼轉到parameter屬性指定的目標 URI。
這樣作的效果是:沒有action類能夠存放咱們的業務邏輯,因此全部須要寫入的邏輯都只能寫到form的reset()或者validate()方法中。validate()的做用是驗證和訪問業務層。由於這裏的action映射不包括forward(也沒有意義),因此不能重定向,只能用默認的那個 forward。這種僅有form的action能夠用來處理數據獲取並forward到另外一個JSP來顯示。
三.僅有Action的actionspa
<action path="/anActionOnlyAction"
type="somePackage.someActionClass">
input="someJSP.jsp"
<forward name="successful" path="someJSP.jsp"/>
<forward name="failed" path="someOtherJSP.jsp"/>
</action>orm
首先,ActionServlet接收到請求後,取得action類實例,調用execute()方法;而後根據返回的ActionForward在配置中找forward,forward到指定的URI或action。
這樣作的效果是:沒有form實例被傳入execute()方法,因而execute()必須本身從請求中獲取參數。Action能夠被forward或者重定向。這種action不能處理經過HTML FORM提交的請求,只能處理連接式的請求。
四.僅有JSP的actionxml
<action path="/aJSPOnlyAction"
type="org.apache.struts.actions.ForwardAction"
parameter="someOtherJSP.jsp"
/>對象
首先,ActionServlet接到請求後調用ForwardAction的execute()方法,execute()根據配置的parameter屬性值來forward到那個URI。
這樣作的效果是:沒有任何form被實例化,比較現實的情形多是form在request更高級別的範圍中定義;或者這個action被用做在應用程序編譯好後充當系統參數,只須要更改這個配置文件而不須要從新編譯系統。
五. 兩個action對應一個formget
<action path="/anAction"
type="somePackage.someActionClass">
name="someForm"
input="someJSP.jsp"
<forward name="successful" path="/anotherAction.do"/>
</action>
<action path="/anotherAction"
type="somePackage.someOtherActionClass">
name="someForm"
input="someOtherJSP.jsp"
<forward name="successful" path="someResultJSP.jsp"/>
</action>
就每一個單獨的action來說,處理上並無和完整的action有什麼實質的區別。這個組合模式能夠被用來傳遞命令對象(form)。須要注意的是在後一個action中一樣會調用form的reset()和validate()方法,所以咱們必須確保form中的信息不被重寫。
處理的方式大體分爲兩種:a) 在request中放入一個指示器代表前一個action有意向後一個action傳遞form,從而在後一個action能夠保留那個form中的值,這一方式只能在使用forward時使用。b) 當使用redirect而不是forward時,能夠把指示器放在session或更高的級別,在命令鏈的最後一環將這個指示器清除。
六. 兩個action對應兩個form
<action path="/anAction"
type="somePackage.someActionClass">
name="someForm"
input="someJSP.jsp"
<forward name="successful" path="/anotherAction.do" redirect="true"/>
</action>
<action path="/anotherAction"
type="somePackage.someOtherActionClass">"
name="someOtherForm"
input="someOtherJSP.jsp"
<forward name="successful" path="someResultJSP.jsp"/>
</action>
這個組合方式跟前一種在流程上沒有太大區別,只是咱們如今對於兩個action分別提供了form,因而代碼看上去更加清晰。因而咱們能夠分別處理WEB 應用程序的輸入和輸出。值得注意的是,後一個action一樣會嘗試往form中寫入那些參數,不過咱們能夠這樣處理:a) 在後一個form中使用另外一套屬性名;b) 只提供getter而不提供setter。大體的處理是這樣:前一個action接收輸入、驗證、而後將數據寫入業務層或持久層,重定向到後一個 action,後一個action手動的從業務層/持久層取出數據,寫入form(經過其餘方式),交給前臺JSP顯示。 這樣作的好處是沒必要保留輸入form中的值,所以可使用redirect而不是forward。這樣就下降了兩個action之間的耦合度,同時也避免了沒必要要的重複提交。