本文講述了如何用Struts建立MVC應用。
Model 1 和Model 2簡介
我們在開發Web應用時經常提到的一個概念是Model 1/Model 2,那麼到底它是什麼意思呢?其實它是對采用JSP技術構成Web應用的不同模型的描述。下面對這個概念做一個簡單的介紹。
Model 1
在使用JAVA技術建立Web應用的實例中,由於JSP技術的發展,很快這種便於掌握和可實現快速開發的技術就成了創建Web應用的主要技術。JSP頁面中可以非常容易地結合業務邏輯(jsp:useBean)、服務端處理過程(jsp:scriplet)和HTML(<html>),在JSP頁面中同時實現顯示,業務邏輯和流程控制,從而可以快速地完成應用開發。現在很多的Web應用就是由一組JSP頁面構成的。這種以JSP為中心的開發模型我們可以稱之為Model 1。
當然這種開發模式在進行快速和小規模的應用開發時,是有非常大的優勢,但是從工程化的角度考慮,它也有一些不足之處:
應用的實現一般是基於過程的,一組JSP頁面實現一個業務流程,如果要進行改動,必須在多個地方進行修改。這樣非常不利於應用擴展和更新。
由於應用不是建立在模塊上的, 業務邏輯和表示邏輯混合在JSP頁面中沒有進行抽象和分離。所以非常不利於應用系統業務的重用和改動。
考慮到這些問題在開發大型的Web應用時必須采用不同的設計模式--這就是Model2
Model 2
Model 2 表示的是基於MVC模式的框架。MVC是Model-View-Controller的簡寫。"Model" 代表的是應用的業務邏輯(通過JavaBean,EJB組件實現), "View" 是應用的表示面(由JSP頁面產生),"Controller" 是提供應用的處理過程控制(一般是一個Servlet),通過這種設計模型把應用邏輯,處理過程和顯示邏輯分成不同的組件實現。這些組件可以進行交互和重用。從而彌補了Model 1的不足。
Model 2具有組件化的優點從而更易於實現對大規模系統的開發和管理,但是開發MVC系統比簡單的JSP開發要復雜許多,它需要更多的時間學習和掌握。同時新東西的引入會帶來新的問題(這讓我想起來關於"自動計算"的一篇文章,中間提到為了降低系統的復雜度,卻導致更高的復雜度)。
必須基於MVC組件的方式重新思考和設計應用結構。原來通過建立一個簡單的JSP頁面就能實現的應用現在變成了多個步驟的設計和實現過程。
所有的頁面和組件必須在MVC框架中實現,所以必須進行附加地開發工作。
MVC本身就是一個非常復雜的系統,所以采用MVC實現Web應用時,最好選一個現成的MVC框架,在此之下進行開發,從而取得事半功倍的效果。現在有很多可供使用的MVC框架,由於Struts有完整的文檔並且相對來講比較簡單,所以用它開發MVC系統還是比較方便地。
Struts的結構和處理流程簡介
Struts是Apache組織的一個項目,像其他的Apache組織的項目一樣,它也是開放源碼項目。Struts是一個比較好的MVC框架提供了對開發MVC系統的底層支持,它采用的主要技術是Servlet,JSP和custom tag library。獲取它的使用版本和具體信息可以查閱 http://jakarta.apache.org網站。
Struts框架的基本構成由下圖所示:
圖 1 struts uml圖
作為一個MVC的框架,Struts對Model、View和Controller都提供了對應的實現組件,對應上面的UML圖,分別進行介紹,並且看看它們是如何結合在一起的。
Controller:控制器的作用是從客戶端接受請求,並且選擇執行相應的業務邏輯,然後把響應結果送回到客戶端。在Struts中Controller功能由圖中ActionServlet和ActionMapping對象構成:核心是一個Servlet類型的對象ActionServlet,它用來接受客戶端的請求。ActionServlet包括一組基於配置的ActionMapping對象,每個ActionMapping對象實現了一個請求到一個具體的Model部分中Action處理器對象之間的映射。
Model: MVC系統中的Model部分從概念上可以分為兩類--系統的內部狀態,和改變系統狀態的動作。Struts為Model部分提供了Action和ActionForm對象:所有的Action處理器對象都是開發者從Struts的Action類派生的子類。Action處理器對象封裝了具體的處理邏輯,調用業務邏輯模塊,並且把響應提交到合適的View組件以產生響應。Struts提供的ActionForm組件對象,它可以通過定義屬性描述客戶端表單數據。開發者可以從它派生子類對象,利用它和Struts提供的自定義標記庫結合可以實現對客戶端的表單數據的良好封裝和支持,Action處理器對象可以直接對它進行讀寫,而不再需要和request、response對象進行數據交互。通過ActionForm組件對象實現了對View和Model之間交互的支持。Struts通常建議使用一組JavaBean表示系統的內部狀態,根據系統的復雜度也可以使用像Entity EJB 和 Session EJB等組件來實現系統狀態。Struts建議在實現時把"做什麼"(Action)和"如何做"(業務邏輯)分離。這樣可以實現業務邏輯的重用。
View:Struts應用中的View部分是通過JSP技術實現的。Struts提供了自定義的標記庫可以使用,通過這些自定義標記可以非常好地和系統的Model部分交互,通過使用這些自定義標記創建的JSP表單,可以實現和Model部分中的ActionForm的映射,完成對用戶數據的封裝,同時這些自定義標記還提供了像模板定制等多種顯示功能。
Struts框架的處理流程清楚的體現了MVC系統的特點,簡單的Struts組件結構如圖2所示。Struts Controller ActionServlet處理客戶請求,利用配置的ActionMapping對象把請求映射到Action處理器對象進行處理。Action處理對象訪問ActionForm中的數據,處理和響應客戶請求,它還調用後台的Bean組件,這些組件封裝了具體的業務邏輯。Action處理器對象根據處理結果通知Controller,Controller進行下一步的處理。
圖2 Struts框架的組件結構圖
利用Struts框架開發MVC系統要做的工作
由於Struts已經為我們提供了一個非常好的MVC框架,我們利用Struts開發MVC系統時可以大大加快開發的速度。在開發時可以采用的一個開發流程如下(引自資料3):
收集和定義應用需求。
基於數據采集和顯示的原則定義和開發"屏幕顯示"需求 。
為每一個"屏幕顯示"定義訪問路徑。
定義ActionMappings建立到應用業務邏輯之間的聯系。
開發滿足"屏幕顯示"需求的所有支持對象。
基於每一個"屏幕顯示"需求提供的數據屬性來創建對應的ActionForm對象
開發被ActionMapping調用的Action對象。
開發應用業務邏輯對象 (Bean,EJB,等等)。
對應ActionMapping設計的流程創建JSP頁面。
建立合適的配置文件struts-config.xml , web.xml。
開發/測試/部署
具體在使用Struts框架時,對應各個部分的開發工作主要包括:
Model部分:采用JavaBean和EJB組件,設計和實現系統的業務邏輯。根據不同的請求從Action派生具體Action處理對象。完成"做什麼"的任務來調用由Bean構成的業務組件。創建由ActionForm 的派生類實現對客戶端表單數據的封裝。
Controller部分:Struts為我們提供了核心控制部分的實現。我們只需要配置ActionMapping對象
View部分:為了使用Model中的ActionForm 對象,我們必須用Struts提供的自定義標記創建HTML 表單。利用Struts提供的自定義標記庫編寫用戶界面把應用邏輯和顯示邏輯分離。Struts框架通過這些自定義標記建立了View和Model之間的聯系。Struts的自定義標記還提供了很多定制頁面的功能。
同時需要編輯兩個配置文件:web.xml和struts-config.xml。通過它們配置Struts系統中的各個模塊之間的交互。下面對這兩個配置文件做一些介紹:
web.xml文件的配置:
web應用中的web.xml是第一個要配置的地方,它描述了系統的Controller對象。在web.xml中增加如下標記
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>application</param-name>
</servlet>
說明:這個servlet對象就是Struts提供的Controller,還可以為它指定初始化參數,比如對系統應用屬性的支持。
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servelt-mapping>
說明:實現客戶請求的url信息和服務器端具體處理的映射關系。
<taglib>
<taglib-url>/WEB-INF/struts-bean.tld</taglib-url>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
???????
說明:添加對Struts提供的應用所使用的自定義標記庫的引用。
struts-config.xml文件的配置:
struts-config.xml是用於建立Controller和Model之間的關系的。它描述了Controller所使用的把請求對應到具體處理的法則,同時它還描述了客戶提供的數據與ActionForm組件的對應映射關系。
在struts-config.xml中增加如下標記
<form-beans>
<form-bean name="loginForm" type="loginForm" />
</form-beans>
說明:<form-bean>標記描述一個具體的ActionForm子類對象,通過它和JSP頁面中的自定標記的結合使用可以實現ActionForm和View之間的數據映射。
<action-mappings>
<action
path="/login"
type="loginAction"
name="loginForm"
input="/login.jsp" ??? />
</action-mappings>
說明:<action-mappings>標記描述了請求和處理的一對一映射關系。input和path屬性唯一的標記了客戶端的一個請求,name屬性描述封裝客戶端的數據的ActionForm子類對象。Type屬性描述處理這個請求的Action子類對象。
通過對兩個配置文件的配置,把Struts框架中MVC的各個部分聯系起來,實現一個真正的MVC系統。
可供參考的例子
編寫一個好的例子演示是比較占篇幅的,可以從 http://jakarta.apache.org/下載Struts最新的發表包,在這個包中有詳細的用戶幫助和API文檔,還有非常好的演示程序可供參考。具體的安裝步驟可以參考附帶的文檔。參考這些例子可以很快地理解如何利用struts框架開發MVC系統。