免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
STRUTS 2 概述(節(jié)選)

引 言

1、MVC思想概述

1.1  Web應(yīng)用的發(fā)展

1.2  Model 1Model 2

1.3  MVC思想

1.4  MVC模式的優(yōu)勢

1.5  常用MVC框架及其特征

2、Struts 2的起源和背景

2.1  Struts 1的基本結(jié)構(gòu)及其存在的問題

2.2  WebWork的基本結(jié)構(gòu)

2.3  Struts 2的起源

3、Struts 2體系介紹.

   3.1  Struts 2的框架架構(gòu)

3.2  Struts 2的標(biāo)簽庫

3.3  Struts 2的控制器組件

4、Struts 1Struts 2的對比

5、WebWorkStruts 2對比

6、總 結(jié) 

 

引 言

Struts 1是全世界第一個發(fā)布的MVC框架,它由Craig McClanahan2001年發(fā)布,該框架一經(jīng)推出,就得到了世界上Java Web開發(fā)者的擁護(hù),經(jīng)過長達(dá)6年時間的錘煉,Struts 1框架更加成熟、穩(wěn)定,性能也有了很好的保證。因此,到目前為止,Struts 1依然是世界上使用最廣泛的MVC框架。

目前,基于WebMVC框架非常多,發(fā)展也很快,每隔一段時間就有一個新的MVC框架發(fā)布,例如像JSFTapestrySpring MVC等。除了這些有名的MVC框架外,還有一些邊緣團(tuán)隊的MVC框架也很有借鑒意義。

對于企業(yè)實際使用MVC框架而言,框架的穩(wěn)定性則應(yīng)該是最值得考慮的問題。一個剛剛起步的框架,可能本身就存在一些隱藏的問題,會將自身的BUG引入自己的應(yīng)用。

雖然Struts 2號稱是一個全新的框架,但這僅僅是相對Struts 1而言。Struts 2Struts 1相比,確實有很多革命性的改進(jìn),但它并不是新發(fā)布的新框架,而是在另一個赫赫有名的框架:WebWork基礎(chǔ)上發(fā)展起來的。從某種程度上來講,Strut2沒有繼承Struts 1的血統(tǒng),而是繼承了WebWork的血統(tǒng)?;蛘哒f,WebWork衍生出了Struts 2,而不是Struts 1衍生了Struts 2。因為Struts 2WebWork的升級,而不是一個全新的框架,因此穩(wěn)定性、性能等各方面都有很好的保證;而且吸收了Struts 1WebWork兩者的優(yōu)勢,因此,是一個非常值得期待的框架。

 

1.  MVC思想概述

今天,我們見到的絕大部分應(yīng)用,都是基于B/S(瀏覽器/服務(wù)器)架構(gòu)的,其中的服務(wù)器就是Web服務(wù)器。可見,Web應(yīng)用是目前廣泛使用的應(yīng)用模式,而Struts 2是一個具有很好的實用價值的Web MVC框架。介紹Struts MVC框架之前,我們首先介紹Web應(yīng)用的發(fā)展歷史和MVC思想。

1.1 Web技術(shù)的發(fā)展

隨著Internet技術(shù)的廣泛使用,Web技術(shù)已經(jīng)廣泛應(yīng)用于Internet上,但早期的Web應(yīng)用全部是靜態(tài)的HTML頁面,用于將一些文本信息呈現(xiàn)給瀏覽者,但這些信息是固定寫在HTML頁面里的,該頁面不具備與用戶交互的能力,沒有動態(tài)顯示的功能。

很自然地,人們希望Web應(yīng)用里應(yīng)該包含一些能動態(tài)執(zhí)行的頁面,最早的CGI(通用網(wǎng)關(guān)接口)技術(shù)滿足了該要求,CGI技術(shù)使得Web應(yīng)用可以與客戶端瀏覽器交互,不再需要使用靜態(tài)的HTML頁面。CGI技術(shù)可以從數(shù)據(jù)庫讀取信息,將這些信息呈現(xiàn)給用戶;還可以獲取用戶的請求參數(shù),并將這些參數(shù)保存到數(shù)據(jù)庫里。

CGI技術(shù)開啟了動態(tài)Web應(yīng)用的時代,給了這種技術(shù)無限的可能性。但CGI技術(shù)存在很多缺點,其中最大的缺點就是開發(fā)動態(tài)Web應(yīng)用難度非常大,而且在性能等各方面也存在限制。到1997年時,隨著Java語言的廣泛使用,Servlet技術(shù)迅速成為動態(tài)Web應(yīng)用的主要開發(fā)技術(shù)。

相比傳統(tǒng)的CGI應(yīng)用而言,Servlet具有大量的優(yōu)勢:

?       Servlet是基于Java語言創(chuàng)建的,而Java語言則內(nèi)建了多線程支持,這一點大大提高了動態(tài)Web應(yīng)用的性能。

?       Servlet應(yīng)用可以充分利用Java語言的優(yōu)勢,例如JDBCJava DataBase Connection)等。同時,Java語言提供了豐富的類庫,這些都簡化了Servlet的開發(fā)。

?       除此之外,Servlet運行在Web服務(wù)器中,由Web服務(wù)器去負(fù)責(zé)管理Servlet的實例化,并對客戶端提供多線程、網(wǎng)絡(luò)通信等功能,這都保證Servlet有更好的穩(wěn)定性和性能。

ServletWeb應(yīng)用中被映射成一個URL(統(tǒng)一資源定位),該URL可以被客戶端瀏覽器請求,當(dāng)用戶向指定URL對應(yīng)的Servlet發(fā)送請求時,該請求被Web服務(wù)器接收到,該Web服務(wù)器負(fù)責(zé)處理多線程、網(wǎng)絡(luò)通信等功能,而Servlet的內(nèi)容則決定了服務(wù)器對客戶端的響應(yīng)內(nèi)容。

 

 

1.1  Servlet的響應(yīng)流程

1.1顯示了Servlet的響應(yīng)流程。

正如圖1.1所顯示的,瀏覽器向Web服務(wù)器內(nèi)指定的Servlet發(fā)送請求,Web服務(wù)器根據(jù)Servlet生成對客戶端的響應(yīng)。

實際上,這是后來所有的動態(tài)Web編程技術(shù)所使用的模型,這種模型都需要一個動態(tài)的程序,或者一個動態(tài)頁面,當(dāng)客戶端向該動態(tài)程序或動態(tài)頁面發(fā)送請求時,Web服務(wù)器根據(jù)該動態(tài)程序來生成對客戶端的響應(yīng)。

到了1998年,微軟發(fā)布了ASP 2.0。它是Windows NT 4 Option Pack的一部分,作為IIS 4.0的外接式附件。它與ASP 1.0的主要區(qū)別在于它的外部組件是可以初始化的,這樣,在ASP程序內(nèi)部的所有組件都有了獨立的內(nèi)存空間,并可以進(jìn)行事務(wù)處理。標(biāo)志著ASP技術(shù)開始真正作為動態(tài)Web編程技術(shù)。

當(dāng)ASP技術(shù)在世界上廣泛流行時,人們很快感受到這種簡單的技術(shù)的魅力:ASP使用VBScript作為腳本語言,它的語法簡單、開發(fā)效率非常高。而且,世界上已經(jīng)有了非常多的VB程序員,這些VB程序員可以很輕易地過渡成ASP程序員——因此,ASP技術(shù)馬上成為應(yīng)用最廣泛的動態(tài)Web開發(fā)技術(shù)。

隨后,由Sun帶領(lǐng)的Java陣營,立即發(fā)布了JSP標(biāo)準(zhǔn),從某種程度上來看,JSPJava陣營為了對抗ASP推出的一種動態(tài)Web編程技術(shù)。

ASPJSP從名稱上如此相似,但它們的運行機(jī)制存在一些差別,這主要是因為VBScript是一種腳本語言,無需編譯,而JSP使用Java作為腳本語句——Java從來就不是解釋型的腳本語言,因此JSP頁面并不能立即執(zhí)行。因此,JSP必須編譯成Servlet,這就是說:JSP的實質(zhì)還是Servlet。不過,書寫JSP比書寫Servlet簡單得多。

JSP的運行機(jī)理如圖1.2所示。 

 

 1.2  JSP的運行機(jī)理

對比圖1.1和圖1.2,發(fā)現(xiàn)不論是Servlet動態(tài)Web技術(shù),還是JSP動態(tài)Web技術(shù),它們的實質(zhì)完全一樣??梢赃@樣理解:JSP是一種更簡單的Servlet技術(shù),這也是JSP技術(shù)出現(xiàn)的意義——作為一個和ASP對抗的技術(shù),簡單就是JSP的最大優(yōu)勢。

隨著實際Web應(yīng)用的使用越來越廣泛,Web應(yīng)用的規(guī)模也越來越大,開發(fā)人員發(fā)現(xiàn)動態(tài)Web應(yīng)用的維護(hù)成本越來越大,即使只需要修改該頁面的一個簡單按鈕文本,或者一段靜態(tài)的文本內(nèi)容,也不得不打開混雜的動態(tài)腳本的頁面源文件進(jìn)行修改——這是一種很大的風(fēng)險,完全有可能引入新的錯誤。

這個時候,人們意識到:使用單純的ASP,或者JSP頁面充當(dāng)過多角色是相當(dāng)失敗的選擇,這對于后期的維護(hù)相當(dāng)不利。慢慢地開發(fā)人員開始在Web開發(fā)中使用MVC模式。

隨后就是Java陣營發(fā)布了一套完整的企業(yè)開發(fā)規(guī)范:J2EE(現(xiàn)在已經(jīng)更名為Java EE),緊跟著微軟也發(fā)布了ASP.NET技術(shù),它們都采用一種優(yōu)秀的分層思想,力圖解決Web應(yīng)用維護(hù)困難的問題。

動態(tài)Web編程技術(shù)大致有如圖1.3所示的路線。

 

 圖1.3  動態(tài)Web編程技術(shù)的發(fā)展歷史

1.2 Model 1Model 2

對于Java陣營的動態(tài)Web編程技術(shù)而言,則經(jīng)歷了所謂的Model 1Model 2時代。

所謂Model 1就是JSP大行其道的時代,在Model 1模式下,整個Web應(yīng)用幾乎全部由JSP頁面組成,JSP頁面接收處理客戶端請求,對請求處理后直接做出響應(yīng)。用少量的JavaBean來處理數(shù)據(jù)庫連接、數(shù)據(jù)庫訪問等操作。

1.4顯示了Model 1的程序流程。

 

 1.4  Model 1的程序流程

Model 1模式的實現(xiàn)比較簡單,適用于快速開發(fā)小規(guī)模項目。但從工程化的角度看,它的局限性非常明顯:JSP頁面身兼ViewController兩種角色,將控制邏輯和表現(xiàn)邏輯混雜在一起,從而導(dǎo)致代碼的重用性非常低,增加了應(yīng)用的擴(kuò)展性和維護(hù)的難度。

早期有大量ASPJSP技術(shù)開發(fā)出來的Web應(yīng)用,這些Web應(yīng)用都采用了Model 1架構(gòu)。

Model 2已經(jīng)是基于MVC架構(gòu)的設(shè)計模式。在Model 2架構(gòu)中,Servlet作為前端控制器,負(fù)責(zé)接收客戶端發(fā)送的請求,在Servlet中只包含控制邏輯和簡單的前端處理;然后,調(diào)用后端JavaBean來完成實際的邏輯處理;最后,轉(zhuǎn)發(fā)到相應(yīng)的JSP頁面處理顯示邏輯。其具體的實現(xiàn)方式如圖1.5所示。

1.5顯示了Model 2的程序流程。

 

 1.5  Model 2的程序流程

正如圖1.5中看到的,Model 2JSP不再承擔(dān)控制器的責(zé)任,它僅僅是表現(xiàn)層角色,僅僅用于將結(jié)果呈現(xiàn)給用戶,JSP頁面的請求與Servlet(控制器)交互,而Servlet負(fù)責(zé)與后臺的JavaBean通信。在Model 2模式下,模型(Model)由JavaBean 充當(dāng),視圖(View)由JSP頁面充當(dāng),而控制器(Controller)則由Servlet充當(dāng)。

由于引入了MVC模式,使Model 2具有組件化的特點,更適用于大規(guī)模應(yīng)用的開發(fā),但也增加了應(yīng)用開發(fā)的復(fù)雜程度。原本需要一個簡單的JSP頁面就能實現(xiàn)的應(yīng)用,在Model 2中被分解成多個協(xié)同工作的部分,需花更多時間才能真正掌握其設(shè)計和實現(xiàn)過程。

Model 2已經(jīng)是MVC設(shè)計思想下的架構(gòu),下面簡要介紹MVC設(shè)計思想的優(yōu)勢。

      注意:對于非常小型的Web站點,如果后期的更新、維護(hù)工作不是特別大,可以使用Model 1的模式來開發(fā)應(yīng)用,而不是使用Model 2的模式。雖然Model 2提供了更好的可擴(kuò)展性及可維護(hù)性,但增加了前期開發(fā)成本。從某種程度上講,Model 2為了降低系統(tǒng)后期維護(hù)的復(fù)雜度,卻導(dǎo)致前期開發(fā)的更高復(fù)雜度。

1.3 MVC思想及其優(yōu)勢

MVC并不是Java語言所特有的設(shè)計思想,也并不是Web應(yīng)用所特有的思想,它是所有面向?qū)ο蟪绦蛟O(shè)計語言都應(yīng)該遵守的規(guī)范。

MVC思想將一個應(yīng)用分成三個基本部分:Model(模型)、View(視圖)和Controller(控制器),這三個部分以最少的耦合協(xié)同工作,從而提高應(yīng)用的可擴(kuò)展性及可維護(hù)性。

起初,MVC模式是針對相同的數(shù)據(jù)需要不同顯示的應(yīng)用而設(shè)計的,其整體的效果如圖1.6所示。

   

    圖1.6  MVC結(jié)構(gòu)

在經(jīng)典的MVC模式中,事件由控制器處理,控制器根據(jù)事件的類型改變模型或視圖,反之亦然。具體地說,每個模型對應(yīng)一系列的視圖列表,這種對應(yīng)關(guān)系通常采用注冊來完成,即:把多個視圖注冊到同一個模型,當(dāng)模型發(fā)生改變時,模型向所有注冊過的視圖發(fā)送通知,接下來,視圖從對應(yīng)的模型中獲得信息,然后完成視圖顯示的更新。

從設(shè)計模式的角度來看,MVC思想非常類似于一個觀察者模式,但與觀察者模式存在少許差別:觀察者模式下觀察者和被觀察者可以是兩個互相對等的對象,但對于MVC思想而言,被觀察者往往只是單純的數(shù)據(jù)體,而觀察者則是單純的視圖頁面。

概括起來,MVC有如下特點。

?       多個視圖可以對應(yīng)一個模型。按MVC設(shè)計模式,一個模型對應(yīng)多個視圖,可以減少代碼的復(fù)制及代碼的維護(hù)量,一旦模型發(fā)生改變,也易于維護(hù)。

?       模型返回的數(shù)據(jù)與顯示邏輯分離。模型數(shù)據(jù)可以應(yīng)用任何的顯示技術(shù),例如,使用JSP頁面、Velocity模板或者直接產(chǎn)生Excel文檔等。

?       應(yīng)用被分隔為三層,降低了各層之間的耦合,提供了應(yīng)用的可擴(kuò)展性。

?       控制層的概念也很有效,由于它把不同的模型和不同的視圖組合在一起,完成不同的請求。因此,控制層可以說是包含了用戶請求權(quán)限的概念。

?       MVC更符合軟件工程化管理的精神。不同的層各司其職,每一層的組件具有相同的特征,有利于通過工程化和工具化產(chǎn)生管理程序代碼。

相對于早期的MVC思想,Web模式下的MVC思想則又存在一些變化,因為對于一個應(yīng)用程序而言,我們可以將視圖注冊給模型,當(dāng)模型數(shù)據(jù)發(fā)生改變時,即時通知視圖頁面發(fā)生改變;而對于Web應(yīng)用而言,即使將多個JSP頁面注冊給一個模型,當(dāng)模型發(fā)生變化時,模型無法主動發(fā)送消息給JSP頁面(因為Web應(yīng)用都是基于請求/響應(yīng)模式的),只有當(dāng)用戶請求瀏覽該頁面時,控制器才負(fù)責(zé)調(diào)用模型數(shù)據(jù)來更新JSP頁面。

      注意:MVC思想與觀察者模式有一定的相似之處,但并不完全相同。經(jīng)典的MVC思想與Web應(yīng)用的MVC思想也存在一定的差別,引起差別的主要原因是因為Web應(yīng)用是一種請求/響應(yīng)模式下應(yīng)用,對于請求/響應(yīng)應(yīng)用,如果用戶不對應(yīng)用發(fā)出請求,視圖無法主動更新自己。

1.4 常用的MVC框架

目前常用的MVC框架,除了Struts 2的兩個前身外,還有一些非常流行的MVC框架,這些框架都提供了較好的層次分隔能力。在實現(xiàn)良好的MVC 分隔的基礎(chǔ)上,還提供一些輔助類庫,幫助應(yīng)用的開發(fā)。

目前常用的MVC框架還有如下一些。

1)   JSF

準(zhǔn)確地說,JSF是一個標(biāo)準(zhǔn),而不是一個產(chǎn)品。目前,JSF已經(jīng)有兩個實現(xiàn)產(chǎn)品可供選擇,包含Sun的參考實現(xiàn)和ApacheMyFaces。大部分的時候,我們所說的JSF都是指Sun的參考實現(xiàn)。目前,JSF是作為JEE 5.0的一個組成部分,與JEE 5.0一起發(fā)布。

JSF的行為方法在POJO中實現(xiàn),JSFManaged Bean無需繼承任何特別的類。因此,無需在表單和模型對象之間實現(xiàn)多余的控制器層。JSF中沒有控制器對象,控制器行為通過模型對象實現(xiàn)。

當(dāng)然,JSF也允許生成獨立的控制器對象。在Struts 1中,Form Bean包含數(shù)據(jù),Action Bean包含業(yè)務(wù)邏輯,二者無法融合在一起。在JSF中,既可以將二者分開,也可以合并在一個對象中,提供更多靈活的選擇。

JSF的事件框架可以細(xì)化到表單中每個字段。JSF依然是基于JSP/Servlet的,仍然是JSP/Servlet架構(gòu),因而學(xué)習(xí)曲線相對簡單。在實際使用過程中,JSF也會存在一些不足

?       作為新興的MVC框架,用戶相對較少,相關(guān)資源也不是非常豐富。

?       JSF并不是一個完全組件化的框架,它依然是基于JSP/Servlet架構(gòu)的。

?       JSF的成熟度還有待進(jìn)一步提高。

2)   Tapestry

Tapestry并不是一種單純的MVC框架,它更像MVC框架和模板技術(shù)的結(jié)合,它不僅包含了前端的MVC框架,還包含了一種視圖層的模板技術(shù),使用Tapestry完全可以與Servlet/JSP API分離,是一種非常優(yōu)秀的設(shè)計。

通過使用Tapestry,開發(fā)者完全不需要使用JSP技術(shù),用戶只需要使用Tapestry提供的模板技術(shù)即可,Tapestry實現(xiàn)了視圖邏輯和業(yè)務(wù)邏輯的徹底分離。

Tapestry使用組件庫替代了標(biāo)簽庫,沒有標(biāo)簽庫概念,從而避免了標(biāo)簽庫和組件結(jié)合的問題。Tapsetry是完全組件化的框架。Tapestr只有組件或頁面兩個概念,因此,鏈接跳轉(zhuǎn)目標(biāo)要么是組件,要么是頁面,沒有多余的path概念。組件名,也就是對象名稱,組件名稱和path名稱合二為一。

Tapestry具有很高的代碼復(fù)用性,在Tapestry中,任何對象都可看作可復(fù)用的組件。JSP開發(fā)者是真正面向?qū)ο?,而不?span>URL解析。對于對頁面要求靈活度相當(dāng)高的系統(tǒng),Tapestry是第一選擇。精確地錯誤報告,可以將錯誤定位到源程序中的行,取代了JSP中那種編譯后的提示。

因此,筆者一直對Tapestry情有獨鐘:如果技術(shù)允許,使用Tapestry會帶給整個應(yīng)用更加優(yōu)雅的架構(gòu),更好的開發(fā)效率。

但是,在實際開發(fā)過程中,采用Tapestry也面臨著一些問題必須考慮:

?       Tapestry的學(xué)習(xí)曲線相對陡峭,國內(nèi)開發(fā)群體不是非?;钴S,文檔不是十分豐富。官方的文檔太過學(xué)院派,缺乏實際的示例程序。

?       Tapestry的組件邏輯比較復(fù)雜,再加上OGNL表達(dá)式和屬性指定機(jī)制,因而難以添加注釋。

3)   Spring MVC

Spring提供了一個細(xì)致完整的MVC框架。該框架為模型、視圖、控制器之間提供了一個非常清晰的劃分,各部分耦合極低。SpringMVC是非常靈活的,它完全基于接口編程,真正實現(xiàn)了視圖無關(guān)。視圖不再強(qiáng)制要求使用JSP,可以使用VelocityXSLT或其他視圖技術(shù)。甚至可以使用自定義的視圖機(jī)制——只需要簡單地實現(xiàn)View接口,并且把對應(yīng)視圖技術(shù)集成進(jìn)來。SpringControllersIoC容器管理。因此,單元測試更加方便。

Spring MVC框架以DispatcherServlet為核心控制器,該控制器負(fù)責(zé)攔截用戶的所有請求,將請求分發(fā)到對應(yīng)的業(yè)務(wù)控制器。

Spring MVC還包括處理器映射、視圖解析、信息國際化、主題解析、文件上傳等。所有控制器都必須實現(xiàn)Controller接口,該接口僅定義ModelAndView handleRequestrequest,response)方法。通過實現(xiàn)該接口來實現(xiàn)用戶的業(yè)務(wù)邏輯控制器。

Spring MVC框架有一個極好的優(yōu)勢,就是它的視圖解析策略:它的控制器返回一個ModelAndView對象,該對象包含視圖名字和Model,Model提供了Bean的名字及其對象的對應(yīng)關(guān)系。視圖名解析的配置非常靈活,抽象的Model完全獨立于表現(xiàn)層技術(shù),不會與任何表現(xiàn)層耦合:JSP、Velocity或者其他的技術(shù)——都可以和Spring整合。

但相對于Tapestry框架而言,Spring MVC依然是基于JSP/Servlet API的。

總體上來看,Spring MVC框架致力于一種完美的解決方案,并與Web應(yīng)用緊緊耦合在一起。這都導(dǎo)致了Spring MVC框架的一些缺點:

?       SpringMVCServlet API耦合,難以脫離Servlet容器獨立運行,降低了Spring MVC框架的可擴(kuò)展性。

?       太過細(xì)化的角色劃分,太過煩瑣,降低了應(yīng)用的開發(fā)效率。

?       過分追求架構(gòu)的完美,有過度設(shè)計的危險。

2Struts 2的起源和背景

Struts 2WebWork優(yōu)秀的設(shè)計思想為核心,吸收了Struts 1的部分優(yōu)點,建立了一個兼容WebWorkStruts 1MVC框架,Struts 2的目標(biāo)是希望可以讓原來使用Struts 1WebWork的開發(fā)人員,都可以平穩(wěn)過渡到使用Struts 2框架。

2.1 Struts 1簡介及存在的問題

從過去的歲月來看,Struts 1是所有MVC框架中不容辯駁的勝利者,不管是市場占有率,還是所擁有的開發(fā)人群,Struts 1都擁有其他MVC框架不可比擬的優(yōu)勢。Struts 1的成功得益于它豐富的文檔、活躍的開發(fā)群體。當(dāng)然,Struts 1是世界上第一個發(fā)布的MVC框架:Struts 1.020016月發(fā)布,這一點可能是使它得到如此廣泛擁戴的主要原因。

為了使讀者可以明白Struts 1的運行機(jī)制,下面將簡要介紹Struts 1的基本框架。

Struts 1框架以ActionServlet作為核心控制器,整個應(yīng)用由客戶端請求驅(qū)動。當(dāng)客戶端向Web應(yīng)用發(fā)送請求時,請求將被Struts 1的核心控制器ActionServlet攔截,ActionServlet根據(jù)請求決定是否需要調(diào)用業(yè)務(wù)邏輯控制器處理用戶請求(實際上,業(yè)務(wù)邏輯控制器還是控制器,它只是負(fù)責(zé)調(diào)用模型來處理用戶請求),當(dāng)用戶請求處理完成后,其處理結(jié)果通過JSP呈現(xiàn)給用戶。

對于整個Struts 1框架而言,控制器就是它的核心,Struts 1的控制器由兩個部分組成:核心控制器和業(yè)務(wù)邏輯控制器。其中核心控制器就是ActionServlet,由Struts 1框架提供;業(yè)務(wù)邏輯控制就是用戶自定義的Action,由應(yīng)用開發(fā)者提供。

對于大部分用戶請求而言,都需要得到服務(wù)器的處理。當(dāng)用戶發(fā)送一個需要得到服務(wù)器處理的請求時,該請求被ActionServlet攔截到,ActionServlet將該請求轉(zhuǎn)發(fā)給對應(yīng)的業(yè)務(wù)邏輯控制器,業(yè)務(wù)邏輯控制器調(diào)用模型來處理用戶請求;如果用戶請求只是希望得到某個URL資源,則由ActionServlet將被請求的資源轉(zhuǎn)發(fā)給用戶。

Struts 1的程序運行流程如圖1.7所示。

 圖1.7  Struts 1的程序運行流程

下面就Struts 1程序流程具體分析MVC中的三個角色。

1)   Model部分

Struts 1Model部分主要由底層的業(yè)務(wù)邏輯組件充當(dāng),這些業(yè)務(wù)邏輯組件封裝了底層數(shù)據(jù)庫訪問、業(yè)務(wù)邏輯方法實現(xiàn)。實際上,對于一個成熟的企業(yè)應(yīng)用而言,Model部分也不是一個簡單的JavaBean所能完成的,它可能是一個或多個EJB組件,可能是一個WebService服務(wù)。總之,Model部分封裝了整個應(yīng)用的所有業(yè)務(wù)邏輯,但整個部分并不是由Struts 1提供的,Struts 1也沒有為實現(xiàn)Model組件提供任何支持。

2)   View部分

Struts 1View部分采用JSP實現(xiàn)。Struts 1提供了豐富的標(biāo)簽庫,通過這些標(biāo)簽庫可以最大限度地減少腳本的使用。這些自定義的標(biāo)簽庫可以輸出控制器的處理結(jié)果。

雖然Struts 1提供了與Ties框架的整合,但Struts 1所支持的表現(xiàn)層技術(shù)非常單一:既不支持FreeMarker、Velocity等模板技術(shù),也不支持JasperReports等報表技術(shù)。

3)   Controller部分

Struts 1Controller由兩個部分組成。

?       系統(tǒng)核心控制器:由Struts 1框架提供,就是系統(tǒng)中的ActionServlet

?       業(yè)務(wù)邏輯控制器:由Struts 1框架提供,就是用戶自己實現(xiàn)的Action實例。

Struts 1的核心控制器對應(yīng)圖1.7中的核心控制器(ActionServlet)。該控制器由Struts 1框架提供,繼承HttpServlet類,因此可以配置成一個標(biāo)準(zhǔn)的Servlet,該控制器負(fù)責(zé)攔截所有HTTP請求,然后根據(jù)用戶請求決定是否需要調(diào)用業(yè)務(wù)邏輯控制器,如果需要調(diào)用業(yè)務(wù)邏輯控制器,則將請求轉(zhuǎn)發(fā)給Action處理,否則直接轉(zhuǎn)向請求的JSP頁面。

業(yè)務(wù)邏輯控制器負(fù)責(zé)處理用戶請求,但業(yè)務(wù)邏輯控制器本身并不具有處理能力,而是調(diào)用Model來完成處理。

Struts 1提供了系統(tǒng)所需要的核心控制器,也為實現(xiàn)業(yè)務(wù)邏輯控制器提供了許多支持。因此,控制器部分就是Struts 1框架的核心。有時候,我們直接將MVC層稱為控制器層。

      提示:對于任何的MVC框架而言,其實只實現(xiàn)了C(控制器)部分,但它負(fù)責(zé)用控制器調(diào)用業(yè)務(wù)邏輯組件,并負(fù)責(zé)控制器與視圖技術(shù)(JSP、FreeMarkerVelocity等)的整合。

對于Struts 1框架而言,因為它與JSP/Servlet耦合非常緊密,因而導(dǎo)致了許多不可避免的缺陷,隨著Web應(yīng)用的逐漸擴(kuò)大,這些缺陷逐漸變成制約Struts 1發(fā)展的重要因素——這也是Struts 2出現(xiàn)的原因。下面具體分析Struts 1中存在的種種缺陷。

1)   支持的表現(xiàn)層技術(shù)單一

Struts 1只支持JSP作為表現(xiàn)層技術(shù),不提供與其他表現(xiàn)層技術(shù),例如VelocityFreeMarker等技術(shù)的整合。這一點嚴(yán)重制約了Struts 1框架的使用,對于目前的很多Java EE應(yīng)用而言,并不一定使用JSP作為表現(xiàn)層技術(shù)。

雖然Struts 1處理完用戶請求后,并沒有直接轉(zhuǎn)到特定的視圖資源,而是返回一個ActionForward對象(可以理解ActionForward是一個邏輯視圖名),在struts-config.xml文件中定義了邏輯視圖名和視圖資源之間的對應(yīng)關(guān)系,當(dāng)ActionServlet得到處理器返回的ActionForword對象后,可以根據(jù)邏輯視圖名和視圖資源之間的對應(yīng)關(guān)系,將視圖資源呈現(xiàn)給用戶。

從上面的設(shè)計來看,不得不佩服Struts 1的設(shè)計者高度解耦的設(shè)計:控制器并沒有直接執(zhí)行轉(zhuǎn)發(fā)請求,而僅僅返回一個邏輯視圖名——實際的轉(zhuǎn)發(fā)放在配置文件中進(jìn)行管理。但因為Struts 1框架出現(xiàn)的年代太早了,那時候還沒有FreeMarkerVelocity等技術(shù),因而沒有考慮與這些FreeMarker、Velocity等視圖技術(shù)的整合。

      提示:Struts 1已經(jīng)通過配置文件管理邏輯視圖名和實際視圖之間的對應(yīng)關(guān)系,只是沒有做到讓邏輯視圖名可以支持更多的視圖技術(shù)。

雖然Struts 1有非常優(yōu)秀的設(shè)計,但由于歷史原因,它沒有提供與更多視圖技術(shù)的整合,這嚴(yán)重限制了Struts 1的使用。

1)   Servlet API嚴(yán)重耦合,難于測試

因為Struts 1框架是在Model 2的基礎(chǔ)上發(fā)展起來的,因此它完全是基于Servlet API的,所以在Struts 1的業(yè)務(wù)邏輯控制器內(nèi),充滿了大量的Servlet API。

看下面的Action代碼片段:

//業(yè)務(wù)邏輯控制器必須繼承Struts 1提供的Action

public class LoginAction extends Action

{

//處理用戶請求的execute方法

public ActionForward execute(

ActionMapping mapping, ActionForm form,

HttpServletRequest request, HttpServletResponse response)

throws     AuctionException  {

//獲取封裝用戶請求參數(shù)的ActionForm對象

//將其強(qiáng)制類型轉(zhuǎn)換為登錄用的ActionForm

LoginForm loginForm = (LoginForm)form;

//當(dāng)用戶名為scott,密碼為tiger時返回成功

if (”scott”.equals(loginForm.getUsername()

&& “tiger”.equals(loginForm.getPassword())

{

//處理成功,返回一個ActionForward對象

return mapping.findForward(”success”);                                    }

else  

{

//處理失敗,返回一個ActionForward對象

return mapping.findForward(”success”);                                    }

    }

}

當(dāng)我們需要測試上面Action類的execute方法時,該方法有4個參數(shù):ActionMapping、ActionForm、HttpServletRequestHttpServletResponse,初始化這4個參數(shù)比較困難,尤其是HttpServletRequestHttpServletResponse兩個參數(shù),通常由Web容器負(fù)責(zé)實例化。

因為HttpServletRequestHttpServletResponse兩個參數(shù)是Servlet API,嚴(yán)重依賴于Web服務(wù)器。因此,一旦脫離了Web服務(wù)器,Action的測試非常困難。

2)   代碼嚴(yán)重依賴于Struts 1 API,屬于侵入式設(shè)計

正如從上面代碼片段中所看到的,Struts 1Action類必須繼承Struts 1Action基類,實現(xiàn)處理方法時,又包含了大量Struts 1 API:如ActionMapping、ActionFormActionForward類。這種侵入式設(shè)計的最大弱點在于,一旦系統(tǒng)需要重構(gòu)時,這些Action類將完全沒有利用價值,成為一堆廢品。

可見,Struts 1Action類這種侵入式設(shè)計導(dǎo)致了較低的代碼復(fù)用。

2.2 WebWork簡介

WebWork雖然沒有Struts 1那樣赫赫有名,但也是出身名門,WebWork來自另外一個優(yōu)秀的開源組織:opensymphony,這個優(yōu)秀的開源組織同樣開發(fā)了大量優(yōu)秀的開源項目,如Qutarz、OSWorkFlow等。實際上,WebWork的創(chuàng)始人則是另一個Java領(lǐng)域的名人:Rickard Oberg(他就是JBossXDoclet的作者)。

相對于Struts 1存在的那些先天性不足而言,WebWork則更加優(yōu)秀,它采用了一種更加松耦合的設(shè)計,讓系統(tǒng)的Action不再與Servlet API耦合。使單元測試更加方便,允許系統(tǒng)從B/S結(jié)構(gòu)向C/S結(jié)構(gòu)轉(zhuǎn)換。

相對于Struts 1僅支持JSP表現(xiàn)層技術(shù)的缺陷而言,WebWork支持更多的表現(xiàn)層技術(shù),如Velocity、FreeMarkerXSLT等。

WebWork可以脫離Web應(yīng)用使用,這一點似乎并沒有太多優(yōu)勢,因為,一個應(yīng)用通常開始已經(jīng)確定在怎樣的環(huán)境下使用。WebWork有自己的控制反轉(zhuǎn)(Inversion of Control)容器,通過控制反轉(zhuǎn),可以讓測試變得更簡單,測試中設(shè)置實現(xiàn)服務(wù)接口的Mock對象完成測試,而不需要設(shè)置服務(wù)注冊。

WebWork 2使用OGNL這個強(qiáng)大的表達(dá)式語言,可以訪問值棧。OGNL對集合和索引屬性的支持非常強(qiáng)大。

WebWork建立在XWork之上,使用ServletDispatcher作為該框架的核心控制器,處理HTTP的響應(yīng)和請求。

從處理流程上來看,WebWorkStruts 1非常類似,它們的核心都由控制器組成,其中控制器都由兩個部分組成:

?       核心控制器ServletDispatcher,該控制器框架提供。

?       業(yè)務(wù)邏輯控制器Action,該控制器由程序員提供。

相對Struts 1ActionServlet API緊緊耦合的弱點來說,WebWorkAction則完全與Servlet API分離,因而該Action更容易測試。

WebWorkAction可以與Servlet API分離,得益于它靈巧的設(shè)計,它使用一個攔截器鏈,負(fù)責(zé)將用戶請求數(shù)據(jù)轉(zhuǎn)發(fā)到Action,并負(fù)責(zé)將Action的處理結(jié)果轉(zhuǎn)換成對用戶的響應(yīng)。

當(dāng)用戶向Web應(yīng)用發(fā)送請求時,該請求經(jīng)過ActionContextCleanUp、SiteMesh等過濾器過濾,由WebWork的核心控制器攔截,如果用戶請求需要WebWork的業(yè)務(wù)邏輯控制器處理,該控制器則調(diào)用Action映射器,該映射器將用戶請求轉(zhuǎn)發(fā)到對應(yīng)的業(yè)務(wù)邏輯控制器。值得注意的是,此時的業(yè)務(wù)邏輯控制器并不是開發(fā)者實現(xiàn)的控制器,而是WebWork創(chuàng)建的控制器代理。

創(chuàng)建控制器代理時,WebWork需要得到開發(fā)者定義的xwork.xml配置文件,控制器代理以用戶實現(xiàn)的控制器作為目標(biāo),以攔截器鏈中的攔截器作為處理(Advice)。

      提示:WebWork中創(chuàng)建控制器代理的方式,就是一種AOP(面向切面編程)編程方式,只是這種AOP中的攔截器由系統(tǒng)提供,因此無需用戶參與。

開發(fā)者自己實現(xiàn)的業(yè)務(wù)邏輯控制器只是WebWork業(yè)務(wù)控制器的目標(biāo)——這就是為什么開發(fā)者自己實現(xiàn)的Action可以與Servlet API分離的原因。當(dāng)開發(fā)者自己的Action處理完HTTP請求后,該結(jié)果只是一個普通字符串,該字符串將對應(yīng)到指定的視圖資源。

指定的試圖資源經(jīng)過攔截器鏈的處理后,生成對客戶端的響應(yīng)輸出。

 上面整個過程的數(shù)據(jù)流圖如圖1.8所示。

 

              1.8  WebWork的數(shù)據(jù)流圖

與前面的Struts 1框架對比,不難發(fā)現(xiàn)WebWork在很多地方確實更優(yōu)秀。

相對Struts 1的種種缺點而言,WebWork存在如下優(yōu)點:

?       Action無需與Servlet API耦合,更容易測試

相對于Struts 1框架中的Action出現(xiàn)了大量Servlet API而言,WebWorkAction更像一個普通Java對象,該控制器代碼中沒有耦合任何Servlet API??聪旅娴?span>WebWorkAction示例:

public class LoginAction implements Action

{

//該字符串常量將作為Action的返回值

private final static String LOGINFAIL=”loginfail”;

 //Action封裝的兩個請求參數(shù)

private String password;

private String username;

//password請求參數(shù)對應(yīng)的getter方法

public String getPassword()

{

return password;

}

//password請求參數(shù)對應(yīng)的setter方法

public void setPassword(String password)

{

this.password = password;

                        }

//username請求參數(shù)對應(yīng)的getter方法

public String getUsername()

{

return username;

               }

//username請求參數(shù)對應(yīng)的setter方法

public void setUsername(String username)

{

this.username = username;

                        }

 //處理用戶請求的execute方法

public String execute() throws Exception

{

if (”yeeku”.equalsIgnoreCase(getUsername())

&& “password”.equals(getPassword()))

{

ActionContext ctx = ActionContext.getContext();

//將當(dāng)前登錄的用戶名保存到Session

Map session = ctx.getSession();

session.put(”username”,getUsername());

return SUCCESS;

              }

else

{

return LOGINFAIL;

                }

         }

}

在上面的Action代碼中,我們看不到任何的Servlet API,當(dāng)系統(tǒng)需要處理兩個請求參數(shù):usernamepassword時,Action并未通過HttpServletRequest對象來獲得請求參數(shù),而是直接調(diào)用訪問該Actionusernamepassword成員屬性——這兩個屬性由Action攔截器負(fù)責(zé)初始化,以用戶請求參數(shù)為其賦值。

即使Action中需要訪問HTTP Session對象,依然沒有在代碼中直接出現(xiàn)HttpSession API,而是以一個Map對象代表了HTTP Session對象。

當(dāng)我們將WebWorkActionStruts 1Action進(jìn)行對比時,不難發(fā)現(xiàn)Struts 1Action確實太臃腫了,確實不如WebWorkAction那么優(yōu)雅。

如果需要測試上面的Action代碼,測試用例的書寫將非常容易,因為execute方法中沒有包含任何Servlet API,甚至沒有WebWorkAPI

?       Action無需與WebWork耦合,代碼重用率高

在上面的Action代碼中,不難發(fā)現(xiàn)WebWork中的Action其實就是一個POJO,該Action僅僅實現(xiàn)了WebWorkAction接口,包含了一個execute方法。

Struts 1中的Action類需要繼承Struts 1Action類。我們知道,實現(xiàn)一個接口和繼承一個類是完全不同的概念:實現(xiàn)一個接口對類的污染要小得多,該類也可以實現(xiàn)其他任意接口,還可以繼承一個父類;但一旦已經(jīng)繼承一個父類,則意味著該類不能再繼承其他父類。

除此之外,Struts 1Action也包含了一個execute方法,但該方法需要4個參數(shù),類型分別是ActionMapping、ActionForm、HttpServletRequestHttpServletResponse,一個包含了這4個參數(shù)的方法,除了在Struts 1框架下有用外,筆者難以想象出該代碼還有任何復(fù)用價值。但WebWorkexecute方法則完全不同,該方法中沒有出現(xiàn)任何Servlet API,也沒有出現(xiàn)任何WebWork API,這個方法在任何環(huán)境下都有重用的價值。

得益于WebWork靈巧的設(shè)計,WebWork中的Action無需與任何Servlet APIWebWork API耦合,從而具有更好的代碼重用率。

?       支持更多的表現(xiàn)層技術(shù),有更好的適應(yīng)性。

正如從圖1.8所見到的,WebWork對多種表現(xiàn)層技術(shù):JSP、VelocityFreeMarker等都有很好的支持,從而給開發(fā)更多的選擇,提供了更好的適應(yīng)性。

2.3  Struts 2起源

經(jīng)過五年多的發(fā)展,Struts 1已經(jīng)成為一個高度成熟的框架,不管是穩(wěn)定性還是可靠性,都得到了廣泛的證明。但由于它太了,一些設(shè)計上的缺陷成為它的硬傷。面對大量新的MVC框架蓬勃興起,Struts 1也開始了血液的更新。

目前,Struts已經(jīng)分化成兩個框架:第一個框架就是傳統(tǒng)Struts 1WebWork結(jié)合后的Struts 2框架。Struts 2雖然是在Struts 1的基礎(chǔ)上發(fā)展起來的,但實質(zhì)上是以WebWork為核心,Struts 2為傳統(tǒng)Struts 1注入了WebWork的設(shè)計理念,統(tǒng)一了Struts 1WebWork兩個框架,允許Struts 1WebWork開發(fā)者同時使用Struts 2框架。

Struts分化出來的另外一個框架是Shale,這個框架遠(yuǎn)遠(yuǎn)超出了Struts 1原有的設(shè)計思想,它與原有的Struts 1的關(guān)聯(lián)很少,它使用全新的設(shè)計思想。Shale更像一個新的框架,而不是Struts的升級。

Shale 在很多方面與Struts存在不同之處,其中有兩點最為突出:

?       StrutsJSF集成,而Shale則是建立在JSF之上。

?       Struts實質(zhì)上是一個巨大的、復(fù)雜的請求處理器;而Shale則是一組能以任何方式進(jìn)行組合的服務(wù),簡單地說,Shale是一種SOA(面向服務(wù)架構(gòu))架構(gòu)。

在后面的介紹中,我們會發(fā)現(xiàn),Struts 2非常類似于WebWork框架,而不像Struts 1框架,因為Struts 2是以WebWork為核心,而不是以Struts 1為核心的。正因為此,許多WebWork開發(fā)者會發(fā)現(xiàn),從WebWork過渡到Struts 2是一件非常簡單的事情。

當(dāng)然,對于傳統(tǒng)的Struts 1開發(fā)者,Struts 2也提供了很好的向后兼容性,Struts 2可與Struts 1有機(jī)整合,從而保證Struts 1開發(fā)者能平穩(wěn)過渡到Struts 2。

3Struts 2體系介紹

Struts 2的體系與Struts 1體系的差別非常大,因為Struts 2使用了WebWork的設(shè)計核心,而不是使用Struts 1的設(shè)計核心。Struts 2大量使用攔截器來處理用戶請求,從而允許用戶的業(yè)務(wù)邏輯控制器與Servlet API分離。

3.1 Struts 2框架架構(gòu)

從數(shù)據(jù)流圖上來看,Struts 2WebWork相差不大,Struts 2同樣使用攔截器作為處理(Advice),以用戶的業(yè)務(wù)邏輯控制器為目標(biāo),創(chuàng)建一個控制器代理。

控制器代理負(fù)責(zé)處理用戶請求,處理用戶請求時回調(diào)業(yè)務(wù)控制器的execute方法,該方法的返回值將決定了Struts 2將怎樣的視圖資源呈現(xiàn)給用戶。

1.9顯示了Struts 2的體系概圖。

  

    1.9  Struts 2的體系概圖

Struts 2框架的大致處理流程如下:

?       瀏覽器發(fā)送請求,例如請求/mypage.action/reports/myreport.pdf等。

?       核心控制器FilterDispatcher根據(jù)請求決定調(diào)用合適的Action

?       WebWork的攔截器鏈自動對請求應(yīng)用通用功能,例如workflow、validation或文件上傳等功能。

?       回調(diào)Actionexecute方法,該execute方法先獲取用戶請求參數(shù),然后執(zhí)行某種數(shù)據(jù)庫操作,既可以是將數(shù)據(jù)保存到數(shù)據(jù)庫,也可以從數(shù)據(jù)庫中檢索信息。實際上,因為Action只是一個控制器,它會調(diào)用業(yè)務(wù)邏輯組件來處理用戶的請求。

?       Actionexecute方法處理結(jié)果信息將被輸出到瀏覽器中,可以是HTML頁面、圖像,也可以是PDF文檔或者其他文檔。此時支持的視圖技術(shù)非常多,既支持JSP,也支持Velocity、FreeMarker等模板技術(shù)。

3.2 Struts 2的配置文件

當(dāng)Struts 2創(chuàng)建系統(tǒng)的Action代理時,需要使用Struts 2的配置文件。

Struts 2的配置文件有兩份:

?       配置Actionstruts.xml文件。

?       配置Struts 2全局屬性的struts.properties文件。

struts.xml文件內(nèi)定義了Struts 2的系列Action,定義Action時,指定該Action的實現(xiàn)類,并定義該Action處理結(jié)果與視圖資源之間的映射關(guān)系。

下面是struts.xml配置文件的示例:

<struts>

<!– Struts 2Action都必須配置在package –>

<package name=”default” extends=”struts-default”>

<!– 定義一個LogonAction,實現(xiàn)類為lee.Logon –>

<action name=”Logon” class=”lee.Logon”>

<!– 配置Action返回input時轉(zhuǎn)入/pages/Logon.jsp頁面 –>

<result name=”input”>/pages/Logon.jsp</result>

<!– 配置Action返回cancel時重定向到WelcomeAction–>

<result name=”cancel” type=”redirect-action”>Welcome</result>

<!– 配置Action返回success時重定向到MainMenuAction –>

<result type=”redirect-action”>MainMenu</result>

<!– 配置Action返回expired時進(jìn)入ChangePasswordAction –>

<result name=”expired” type=”chain”>ChangePassword</result>

</action>

<!– 定義LogoffAction,實現(xiàn)類為lee.Logoff –>

<action name=”Logoff” class=” lee.Logoff”>

<!– 配置Action返回success時重定向到MainMenuAction –>

<result type=”redirect-action”>Welcome</result>

</action>

</package>

</struts>

在上面的struts.xml文件中,定義了兩個Action。定義Action時,不僅定義了Action的實現(xiàn)類,而且的定義Action的處理結(jié)果時,指定了多個result,result元素指定execute方法返回值和視圖資源之間的映射關(guān)系。對于如下配置片段:

<result name=”cancel” type=”redirect-action”>Welcome</result>

表示當(dāng)execute方法返回cancel的字符串時,跳轉(zhuǎn)到WelcomeAction。定義result元素時,可以指定兩個屬性:typename。其中name指定了execute方法返回的字符串,而type指定轉(zhuǎn)向的資源類型,此處轉(zhuǎn)向的資源可以是JSP,也可以是FreeMarker等,甚至是另一個Action——這也是Struts 2可以支持多種視圖技術(shù)的原因。

除此之外,Struts 2還有一個配置Struts 2全局屬性的Properties文件:struts.properties。該文件的示例如下:

#指定Struts 2處于開發(fā)狀態(tài)

struts.devMode = false

//指定當(dāng)Struts 2配置文件改變后,Web框架是否重新加載Struts 2配置文件struts.configuration.xml.reload=true

正如上面見到的,struts.properties文件的形式是系列的key、value對,它指定了Struts 2應(yīng)用的全局屬性。

3.3 Strut 2的標(biāo)簽庫

Struts 2的標(biāo)簽庫也是Struts 2的重要組成部分,Struts 2的標(biāo)簽庫提供了非常豐富的功能,這些標(biāo)簽庫不僅提供了表現(xiàn)層數(shù)據(jù)處理,而且提供了基本的流程控制功能,還提供了國際化、Ajax支持等功能。

通過使用Struts 2的標(biāo)簽,開發(fā)者可以最大限度地減少頁面代碼的書寫。

看下面的JSP頁面的表單定義片段:

<!–  定義一個Action –>

<form method=”post” action=”basicvalid.action”>

<!– 下面定義三個表單域 –>

    名字:<input type=”text” name=”name”/><br>

    年紀(jì):<input type=”text” name=”age”/><br>

    喜歡的顏色:<input type=”text” name=”favorite”/><br>

                                 <!– 定義一個輸出按鈕 –>

    <input type=”submit” value=”提交“/>

</form>

上面頁面使用了傳統(tǒng)的HTML標(biāo)簽定義表單元素,還不具備輸出校驗信息的功能,但如果換成如下使用Struts 2標(biāo)簽的定義方式:

<!– 使用Struts 2標(biāo)簽定義一個表單 –>

<s:form method=”post” action=”basicvalid.action”>

<!– 下面使用Struts 2標(biāo)簽定義三個表單域 –>

<s:textfield label=”名字” name=”name”/>

<s:textfield label=”年紀(jì)” name=”age”/>

<s:textfield label=”喜歡的顏色” name=”answer”/>

<!– 定義一個提交按鈕 –>

<s:submit/>

</s:form>

則頁面代碼更加簡潔,而且有更簡單的錯誤輸出。圖1.10是上面使用Struts 2標(biāo)簽執(zhí)行數(shù)據(jù)校驗后的輸出。

1.10  使用Struts 2標(biāo)簽的效果

      提示:Struts 2的標(biāo)簽庫的功能非常復(fù)雜,該標(biāo)簽庫幾乎可以完全替代JSTL的標(biāo)簽庫。而且Struts 2的標(biāo)簽支持表達(dá)式語言,這種表達(dá)式語言支持一個強(qiáng)大和靈活的表達(dá)式語言:OGNLObject Graph Notation Language),因此功能非常強(qiáng)大。

3.4 Struts 2的控制器組件

Struts 2的控制器組件是Struts 2框架的核心,事實上,所有MVC框架都是以控制器組件為核心的。正如前面提到的,Struts 2的控制器由兩個部分組成:FilterDispatcher和業(yè)務(wù)控制器Action

實際上,Struts 2應(yīng)用中起作用的業(yè)務(wù)控制器不是用戶定義的Action,而是系統(tǒng)生成的Action代理,但該Action代理以用戶定義的Action為目標(biāo)。

下面是Struts 2Action代碼示例:

public class LoginAction

{

//封裝用戶請求參數(shù)的username屬性

private String username;

//封裝用戶請求參數(shù)的password屬性

private String password;

 //username屬性的getter方法

public String getUsername()

{

return username;

               }

//username屬性的setter方法

public void setUsername(String username)

{

this.username = username;

                        }

//password屬性的getter方法

public String getPassword()

{

return password;

               }

//password屬性的setter方法

public void setPassword(String password)

{

this.password = password;

                        }

//處理用戶請求的execute方法

public String execute() throws Exception

{

//如果用戶名為scott,密碼為tiger,則登錄成功

if (getUsername().equals(”scott” )

&& getPassword().equals(”tiger” ) )

{

return “success”;

                }

else

{

return “error”;

              }

       }

}

通過查看上面的Action代碼,發(fā)現(xiàn)該ActionWebWork中的Action更徹底,該Action無需實現(xiàn)任何父接口,無需繼承任何Struts 2基類,該Action類完全是一個POJO(普通、傳統(tǒng)的Java對象),因此具有很好的復(fù)用性。

歸納起來,該Action類有如下優(yōu)勢:

?       Action類完全是一個POJO,因此具有很好的代碼復(fù)用性。

?       Action類無需與Servlet API耦合,因此進(jìn)行單元測試非常簡單。

?       Action類的execute方法僅返回一個字符串作為處理結(jié)果,該處理結(jié)果可映射到任何的視圖,甚至是另一個Action。

4Struts 2Struts 1的對比

經(jīng)過上面簡要介紹,不難發(fā)現(xiàn),Struts 2確實在Struts 1上做出了巨大的改進(jìn),的確是一個非常具有實用價值的MVC框架。          

Struts 1Struts 2在各方面的簡要對比。

?       Action實現(xiàn)類方面的對比:Struts 1要求Action類繼承一個抽象基類;Struts 1的一個具體問題是使用抽象類編程而不是接口。Struts 2 Action類可以實現(xiàn)一個Action接口,也可以實現(xiàn)其他接口,使可選和定制的服務(wù)成為可能。Struts 2提供一個ActionSupport基類去實現(xiàn)常用的接口。即使Action接口不是必須實現(xiàn)的,只有一個包含execute方法的POJO類都可以用作Struts 2Action。

?       線程模式方面的對比:Struts 1 Action是單例模式并且必須是線程安全的,因為僅有Action的一個實例來處理所有的請求。單例策略限制了Struts 1 Action能做的事,并且要在開發(fā)時特別小心。Action資源必須是線程安全的或同步的;Struts 2 Action對象為每一個請求產(chǎn)生一個實例,因此沒有線程安全問題。

?       Servlet依賴方面的對比:Struts 1 Action依賴于Servlet API,因為Struts 1 Actionexecute方法中有HttpServletRequestHttpServletResponse方法。Struts 2 Action不再依賴于Servlet API,從而允許Action脫離Web容器運行,從而降低了測試Action的難度。 當(dāng)然,如果Action需要直接訪問HttpServletRequestHttpServletResponse參數(shù),Struts 2 Action仍然可以訪問它們。但是,大部分時候,Action都無需直接訪問HttpServetRequestHttpServletResponse,從而給開發(fā)者更多靈活的選擇。

?       可測性方面的對比:測試Struts 1 Action的一個主要問題是execute方法依賴于Servlet API,這使得Action的測試要依賴于Web容器。為了脫離Web容器測試Struts 1Action,必須借助于第三方擴(kuò)展:Struts TestCase,該擴(kuò)展下包含了系列的Mock對象(模擬了HttpServetRequestHttpServletResponse對象),從而可以脫離Web容器測試Struts 1Action類。Struts 2 Action可以通過初始化、設(shè)置屬性、調(diào)用方法來測試。

?       封裝請求參數(shù)的對比:Struts 1使用ActionForm對象封裝用戶的請求參數(shù),所有的ActionForm必須繼承一個基類:ActionForm。普通的JavaBean不能用作ActionForm,因此,開發(fā)者必須創(chuàng)建大量的ActionForm類封裝用戶請求參數(shù)。雖然Struts 1提供了動態(tài)ActionForm來簡化ActionForm的開發(fā),但依然需要在配置文件中定義ActionForm;Struts 2直接使用Action屬性來封裝用戶請求屬性,避免了開發(fā)者需要大量開發(fā)ActionForm類的煩瑣,實際上,這些屬性還可以是包含子屬性的Rich對象類型。如果開發(fā)者依然懷念Struts 1 ActionForm的模式,Struts 2提供了ModelDriven模式,可以讓開發(fā)者使用單獨的Model對象來封裝用戶請求參數(shù),但該Model對象無需繼承任何Struts 2基類,是一個POJO,從而降低了代碼污染。

?       表達(dá)式語言方面的對比:Struts 1整合了JSTL,因此可以使用JSTL表達(dá)式語言。這種表達(dá)式語言有基本對象圖遍歷,但在對集合和索引屬性的支持上則功能不強(qiáng);Struts 2可以使用JSTL,但它整合了一種更強(qiáng)大和靈活的表達(dá)式語言:OGNLObject Graph Notation Language),因此,Struts 2下的表達(dá)式語言功能更加強(qiáng)大。

?       綁定值到視圖的對比:Struts 1使用標(biāo)準(zhǔn)JSP機(jī)制把對象綁定到視圖頁面;Struts 2使用“ValueStack”技術(shù),使標(biāo)簽庫能夠訪問值,而不需要把對象和視圖頁面綁定在一起。

?       類型轉(zhuǎn)換的對比:Struts 1 ActionForm 屬性通常都是String類型。Struts 1使用Commons-Beanutils進(jìn)行類型轉(zhuǎn)換,每個類一個轉(zhuǎn)換器,轉(zhuǎn)換器是不可配置的;Struts 2使用OGNL進(jìn)行類型轉(zhuǎn)換,支持基本數(shù)據(jù)類型和常用對象之間的轉(zhuǎn)換。

?       數(shù)據(jù)校驗的對比:Struts 1支持在ActionForm重寫validate方法中手動校驗,或者通過整合Commons alidator框架來完成數(shù)據(jù)校驗。Struts 2支持通過重寫validate方法進(jìn)行校驗,也支持整合XWork校驗框架進(jìn)行校驗。

?       Action執(zhí)行控制的對比:Struts 1支持每一個模塊對應(yīng)一個請求處理(即生命周期的概念),但是模塊中的所有Action必須共享相同的生命周期。Struts 2支持通過攔截器堆棧(Interceptor Stacks)為每一個Action創(chuàng)建不同的生命周期。開發(fā)者可以根據(jù)需要創(chuàng)建相應(yīng)堆棧,從而和不同的Action一起使用。

5WebWorkStruts 2對比

從某種程度上來看,Struts 2WebWork的升級,而不是Struts 1的升級,甚至在ApacheStruts 2的官方文檔都提到:WebWorkStruts 2是一次平滑的過渡。實際上,Struts 2.0其實是WebWork 2.3而已,從WebWork 2.2遷移到Struts 2.0不會比從WebWork 2.12.2更麻煩。

在很多方面,Struts 2僅僅是改變了WebWork下的名稱,因此,如果開發(fā)者具有WebWork的開發(fā)經(jīng)驗,將可以更加迅速地進(jìn)入Struts 2的開發(fā)領(lǐng)域。

下面是Struts 2WebWork命名上存在改變(見表1.1):

Struts 2成員

    WebWork成員

com.opensymphony.xwork2.*

    com.opensymphony.xwork.*

org.apache.Struts2.*

    com.opensymphony.webwork.*

struts.xml

    xwork.xml

struts.properties

    webwork.properties

Dispatcher  

    DispatcherUtil

org.apache.Struts2.config.Settings

    com.opensymphony.webwork.config.Configuration

1.1  Struts 2WebWork成員名稱的對應(yīng)

除此之外,Struts 2也刪除了WebWork中少量特性:

?       AroundInterceptorStruts 2不再支持WebWork中的AroundInterceptor。如果應(yīng)用程序中需要使用AroundInterceptor,則應(yīng)該自己手動導(dǎo)入WebWork中的AroundInterceptor類。

?       副文本編輯器標(biāo)簽:Struts 2不再支持WebWork的富文本編輯器,如果應(yīng)用中需要使用富文本編輯器,則應(yīng)該使用Dojo的富文本編輯器。

?       IoC容器支持:Struts 2不再支持內(nèi)建的IoC容器,而改為全面支持SpringIoC容器,以SpringIoC容器作為默認(rèn)的Object工廠。

6. 總 結(jié)

本節(jié)課大致介紹了Web應(yīng)用的開發(fā)歷史,從歷史的角度介紹了Model 1Model 2的簡要模型和特征,進(jìn)而介紹了MVC模式的主要策略和主要優(yōu)勢。接著介紹了常用的MVC框架,包括JSF、TapestrySpring MVC,以及這些框架的基本知識和相關(guān)特征。本節(jié)重點介紹了Struts 2的兩個前身:Struts 1WebWork,以及這兩個框的架構(gòu)和主要特征,從而引申出對Struts 2起源的介紹。最后大致介紹了Struts 2框架的體系,包括Struts 2框架的架構(gòu)、標(biāo)簽庫、控制器組件等,并就Struts 1Struts 2的相關(guān)方面進(jìn)行了比較。

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
基于mvc模式的struts框架概述
MVC基礎(chǔ)、Model2的MVC和Struts2的MVC
SSH框架總結(jié)(框架分析+環(huán)境搭建+實例源碼下載)
Struts2入門基礎(chǔ)
WebWork In Action學(xué)習(xí)筆記(一) WebWork的概貌 - 吾將上下而求索...
mayong--淺析struts 體系結(jié)構(gòu)與工作原理
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服