開發最佳實踐:在Web應用開發中優化Struts框架
Struts是一種開源框架,可用來構建Web應用程序,它基于流行的Model-View-Controller (MVC2) 設計范型。該框架構建在一些標準的技術之上,比如Java Servlets、JavaBeans、ResourceBundles和XML,并且可提供靈活和可擴展的組件。
關于Struts更多內容,請參閱:Struts框架應用專題
Struts以ActionServlet的形式實現了Controller層,并建議使用JSP標記庫構建View層。Struts 通過Action類提供了圍繞Model層的包裝器。圖1展示了基于Model-View-Controller設計的Struts框架。
圖1.Struts和MVC
Struts 組件概覽
首先,我們在***實踐上下文中解釋 Struts 組件,以及它們在 Web 應用程序開發中所起的作用。
Action
應用程序的每個 Action 都會擴展 Struts 的 org.apache.struts.action.Action 類。這些 Action 類為應用程序的 Model 層提供了一個接口,充當圍繞業務邏輯的包裝器。每個 Action 類都必須向 perform() 方法提供其特定于用例的實現。perform() 方法經常返回類型 ActionForward 的一個值。
ActionForm
應用程序的 ActionForm 擴展了 Struts 的 org.apache.struts.action.ActionForm 類。ActionForm 是一些封裝和驗證請求參數的簡單 JavaBean。要驗證請求數據,ActionForm 的 validate() 方法必須給出一個特定于該情況的實現。ActionForm 作為運載工具,向 Action 類提供請求數據。一個 JSP 對象與各自的 ActionForm 對象相結合,構成應用程序的 View 層。在該層,幾乎 JSP 對象的每個表單字段都映射到相應的 ActionForm 的屬性。
JSP 定制標記庫
JSP 定制標記庫是用標記表示的一組行為的集合。這是 JSP Specification 1.1 的一個強大特性;它將其他應用程序層的表示區別了開來。這些庫易于使用,而且可以以一種類似 XML 的方式來讀取。只要盡量少地在其中使用 Java scriptlet,就可以輕松維護 JSP 組件。Struts 提供的 JSP 標記包括 HTML、邏輯和 bean 標記。
ActionErrors
可以使用 ActionError 來支持異常處理。ActionError 捕捉應用程序異常,并將其傳送給 View 層。每個異常都是一個 ActionError 實例的集合。ActionError 可以封裝錯誤消息,而 Presentation 層中的 </html:errors> 可以呈現 ActionError 集合內的所有錯誤消息。
***實踐 1. 跨多個 ActionForm 重用數據
熟悉了 Struts 組件之后,就可以繼續學習如何充分利用這一框架。首先,Struts 建議將每個 JSP 對象與一個 ActionForm 相關聯,后者可以封裝屏幕上顯示的數據??梢酝ㄟ^ ActionForm 內的附加方法來訪問 JSP 對象內的表單數據。清單 1 展示了 ActionForm 標記在 View 層中的傳統方法。
- 清單 1. 使用 ActionForm
- <html:form action="/bp1">
- <html:text property="attrib1" />
- </html:form >
這個ActionForm被稱為 “BP1AForm”,它包括屬性attrib1及其getter和setter方法。在配置文件struts-config.xml中,行為 “/bp1” 通過name屬性映射到 bp1AForm。這有助于在JSP中顯示數據。要實現這一***實踐,Struts 建議您進行以下兩個操作:
創建一個 JavaBean(BP1BForm),且其屬性是 BP1AForm 屬性的子集,還要創建這些屬性的 getter 和 setter 方法。通過將這個 bean 與 BP1AForm 關聯,用 bean BP1BForm 的屬性替代 BP1AForm 中的屬性。現在就可以通過 BP1BForm 訪問 BP1AForm 中的屬性子集了。清單2展示了訪問的方式。
- 清單 2. 訪問 JSP 中的表單屬性
- <html:form action="/bp1">
- <bean:define name="bp1AForm" property="bp1BForm" id="bp1B"
- type="com.ibm.dw.webarch.struts.BP1BForm" />
- <html:text name="bp1B" property="subsetAtt1" />
- </html:form >
要點
這種實踐的主要優勢是可用于多個 ActionForm 訪問一個屬性集。在遵循這一***實踐的同時,需要記住以下幾點:
1.Struts 實現 <bean:define/> 標記。
2.當代碼 <%@ taglib uri="struts-bean.tld" prefix="bean" %> 指向 struts-bean.tld 時,<bean:define/> 標記開始在 JSP 組件內工作。
3.由 ActionForm 擴展而來的 BP1AForm 驗證框架必須驗證 BP1BForm 的數據。
4.當在應用程序中創建 Action 類時,不需要直接擴展 org.apache.struts.action.Action,可以通過擴展 org.apache.struts.action.Action 創建一個 Action 類(IntermediateAction),用于處理應用程序中的常見事務。所有其他的 Action 類都擴展 IntermediateAction 類。
#p#
***實踐 2. 使用 Action 類處理請求
通常,在使用這個 Struts 框架時,對于 JSP 組件請求應用程序執行的每個動作,應用程序都必須擴展Struts的org.apache.struts.action.Action以創建Action類。在處理請求時,單個的 Action 類與應用程序的 Model 層連接。要實現這一***實踐,Struts 建議您遵循以下步驟:
1.通過擴展 org.apache.struts.action.Action 創建一個 Action 類,比如 BP2Action。
2.通過擴展 BP2Action 在 Web 應用程序中創建所有其他 Action 類。
3.在 BP2Action 類中創建一個方法 performTask(),就像在公共抽象類 ActionForward performTask(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException 中一樣。
4.在BP2Action 類中向應用程序添加一個或多個泛型方法,比如 serverSideValidate()??紤]以下因素后決定方法的訪問修飾符:
◆如果所有 Action 類都必須實現此方法,則讓其為抽象。
◆如果某些 Action 類提供一個特定的實現,則將此方法聲明為受保護,并給它一個默認實現。
5.在 BP2Action 類中,將方法 perform() 聲明為 final。調用上述的泛型方法(通常在處理請求前調用該方法)?,F在調用 步驟 3 中創建的方法 performTask()。
在每個擴展 BP2Action 的 Action 類,添加具有特定實現的方法 performTask()。
優勢
這一實踐有兩個主要優勢。首先,它避免了 Web 應用程序中每個 Action 類的冗余代碼。其次,通過將 Action 類的行為集中在一起,使應用程序能夠更多地控制通用的任務。
#p#
***實踐 3. 使用 ActionForm 處理會話數據
在一個基于 Struts 的 Web 應用程序中,每個 ActionForm 都擴展 org.apache.struts.action.ActionForm 類。這些 ActionForm 封裝頁面數據,并提供一個驗證框架來驗證請求參數。
大多數 Web 應用程序都在會話中保持數據,使其在整個應用程序過程中可用。這種***實踐實現了這種 Web 應用程序特性。它允許方法 toSession() 和 fromSession() 將會話數據移動到表單數據或從表單數據移回。因此,它實現了在 Web 應用程序中保持會話數據。要遵循一***實踐,執行以下步驟:
通過擴展 org.apache.struts.action.ActionForm 創建一個名為 BP3Form 的抽象類。在BP3Form類中,添加具有訪問修飾語的方法,就像在公共抽象類 void toSession(SessionData sessionData) 和 void fromSession(SessionData sessionData) 中一樣。
在每個 ActionForm 類中,擴展 BP3Form 并實現這些抽象方法(表單數據通過它們傳遞到會話或從會話傳回)。 相應的 Action 類可以決定這些方法的調用順序。例如,可以在決定 actionForward 之前調用 ActionForm 上的方法 toSession()。
何時使用這一實踐,這一實踐最適用于:會話數據是單一對象和/或每個頁操作或使用會話數據。
#p#
***實踐 4.有效處理異常
傳統地,當在 Action 類中發生應用程序異常時,異常首先被寫入日志。然后此類創建一個 ActionError 并在合適的作用域中存儲它。然后 Action 類再將控制轉交給合適的 ActionForward。清單 3 展示了 Action 類是如何處理異常的。
- 清單 3. Action 類中的異常處理
- try {
- //Code in Action class
- }
- catch (ApplicationException e) {
- //log exception
- ActionErrors actionErrors = new ActionErrors();
- ActionError actionError = new ActionError(e.getErrorCode());
- actionErrors.add(ActionErrors.GLOBAL_ERROR, actionError);
- saveErrors(request, actionErrors);
- }
傳統的異常處理過程在每個 Action 類中保存異常信息,而***實踐 4 則在處理異常時避免冗余代碼。要使用這一***實踐,Struts 建議您遵循以下步驟:
1.通過擴展 org.apache.struts.action.Action 創建一個 Action 類,比如 BP4Action。
2.通過擴展 BP4Action 在 Web 應用程序中創建所有其他 Action 類。
3.在 BP4Action 中聲明變量 ActionErrors actionErrors = new ActionErrors();。
4.在 BP4Action 中創建方法 performTask(),就像在公共抽象類 ActionForward performTask(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, ActionErrors actionErrors) throws IOException, ServletException 中一樣。
6.在BP4Action中將方法perform()聲明為final。然后調用泛型方法(這些方法總是在處理請求前調用)?,F在調用在前一個步驟中創建的 performTask()。
7.在每個 Action 類中實現方法performTask()的同時(通過擴展 BP4Action),像清單 4 那樣處理應用程序異常。
- 清單 4. 有效使用 ActionErrors
- try {
- //Code in Action class
- }
- catch(ApplicationException appException) {
- //Log exception
- //Add error to actionErrors
- actionErrors.add(ActionErrors.GLOBAL_ERROR,
- new ActionError(appException.getErrorCode()));
- }
在BP4Action中,調用方法performTask()之后,通過saveErrors(request, errors)保存ActionErrors。
優勢
這一實踐主要的優勢是:避免了每個處理 ActionErrors的Action類中的代碼冗余。
結束語
對開發團隊而言,構建易于維護的Web應用程序是一項非常具有挑戰性的任務。使用Struts等成熟的框架有助于實現通常與構建應用程序相關的基礎設施代碼。Struts 框架提供了一組標準接口,用于將業務邏輯插入到應用程序中。此外,還提供了一種跨開發團隊的一致機制,用于執行用戶數據驗證、屏幕導航等任務,以及用于簡化開發屏幕的一組定制標記庫。
本文給出的4種***實踐對您充分利用這種框架的特性十分重要。它們不僅能夠提高代碼的模塊化程度和應用程序的可重用性,還能減少代碼冗余。對于構建可擴展的Web應用程序,這是至關重要的。
【編輯推薦】