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