欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
STRUTS 2 概述(節選)

引 言

1、MVC思想概述

1.1  Web應用的發(fā)展

1.2  Model 1Model 2

1.3  MVC思想

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

1.5  常用MVC框架及其特征

2、Struts 2的起源和背景

2.1  Struts 1的基本結構及其存在的問(wèn)題

2.2  WebWork的基本結構

2.3  Struts 2的起源

3、Struts 2體系介紹.

   3.1  Struts 2的框架架構

3.2  Struts 2的標簽庫

3.3  Struts 2的控制器組件

4、Struts 1Struts 2的對比

5、WebWorkStruts 2對比

6、總 結 

 

引 言

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

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

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

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

 

1.  MVC思想概述

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

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

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

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

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

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

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

?       Servlet應用可以充分利用Java語(yǔ)言的優(yōu)勢,例如JDBCJava DataBase Connection)等。同時(shí),Java語(yǔ)言提供了豐富的類(lèi)庫,這些都簡(jiǎn)化了Servlet的開(kāi)發(fā)。

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

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

 

 

1.1  Servlet的響應流程

1.1顯示了Servlet的響應流程。

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

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

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

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

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

ASPJSP從名稱(chēng)上如此相似,但它們的運行機制存在一些差別,這主要是因為VBScript是一種腳本語(yǔ)言,無(wú)需編譯,而JSP使用Java作為腳本語(yǔ)句——Java從來(lái)就不是解釋型的腳本語(yǔ)言,因此JSP頁(yè)面并不能立即執行。因此,JSP必須編譯成Servlet,這就是說(shuō):JSP的實(shí)質(zhì)還是Servlet。不過(guò),書(shū)寫(xiě)JSP比書(shū)寫(xiě)Servlet簡(jiǎn)單得多。

JSP的運行機理如圖1.2所示。 

 

 1.2  JSP的運行機理

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

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

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

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

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

 

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

1.2 Model 1Model 2

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

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

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

 

 1.4  Model 1的程序流程

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

早期有大量ASPJSP技術(shù)開(kāi)發(fā)出來(lái)的Web應用,這些Web應用都采用了Model 1架構。

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

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

 

 1.5  Model 2的程序流程

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

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

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

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

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

MVC并不是Java語(yǔ)言所特有的設計思想,也并不是Web應用所特有的思想,它是所有面向對象程序設計語(yǔ)言都應該遵守的規范。

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

起初,MVC模式是針對相同的數據需要不同顯示的應用而設計的,其整體的效果如圖1.6所示。

   

    圖1.6  MVC結構

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

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

概括起來(lái),MVC有如下特點(diǎn)。

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

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

?       應用被分隔為三層,降低了各層之間的耦合,提供了應用的可擴展性。

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

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

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

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

1.4 常用的MVC框架

目前常用的MVC框架,除了Struts 2的兩個(gè)前身外,還有一些非常流行的MVC框架,這些框架都提供了較好的層次分隔能力。在實(shí)現良好的MVC 分隔的基礎上,還提供一些輔助類(lèi)庫,幫助應用的開(kāi)發(fā)。

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

1)   JSF

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

JSF的行為方法在POJO中實(shí)現,JSFManaged Bean無(wú)需繼承任何特別的類(lèi)。因此,無(wú)需在表單和模型對象之間實(shí)現多余的控制器層。JSF中沒(méi)有控制器對象,控制器行為通過(guò)模型對象實(shí)現。

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

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

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

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

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

2)   Tapestry

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

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

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

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

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

但是,在實(shí)際開(kāi)發(fā)過(guò)程中,采用Tapestry也面臨著(zhù)一些問(wèn)題必須考慮:

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

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

3)   Spring MVC

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

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

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

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

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

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

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

?       太過(guò)細化的角色劃分,太過(guò)煩瑣,降低了應用的開(kāi)發(fā)效率。

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

2Struts 2的起源和背景

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

2.1 Struts 1簡(jiǎn)介及存在的問(wèn)題

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

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

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

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

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

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

 圖1.7  Struts 1的程序運行流程

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

1)   Model部分

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

2)   View部分

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

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

3)   Controller部分

Struts 1Controller由兩個(gè)部分組成。

?       系統核心控制器:由Struts 1框架提供,就是系統中的ActionServlet。

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

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

業(yè)務(wù)邏輯控制器負責處理用戶(hù)請求,但業(yè)務(wù)邏輯控制器本身并不具有處理能力,而是調用Model來(lái)完成處理。

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

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

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

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

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

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

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

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

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

1)   Servlet API嚴重耦合,難于測試

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

看下面的Action代碼片段:

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

public class LoginAction extends Action

{

//處理用戶(hù)請求的execute方法

public ActionForward execute(

ActionMapping mapping, ActionForm form,

HttpServletRequest request, HttpServletResponse response)

throws     AuctionException  {

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

//將其強制類(lèi)型轉換為登錄用的ActionForm

LoginForm loginForm = (LoginForm)form;

//當用戶(hù)名為scott,密碼為tiger時(shí)返回成功

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

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

{

//處理成功,返回一個(gè)ActionForward對象

return mapping.findForward(”success”);                                    }

else  

{

//處理失敗,返回一個(gè)ActionForward對象

return mapping.findForward(”success”);                                    }

    }

}

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

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

2)   代碼嚴重依賴(lài)于Struts 1 API,屬于侵入式設計

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

可見(jiàn),Struts 1Action類(lèi)這種侵入式設計導致了較低的代碼復用。

2.2 WebWork簡(jiǎn)介

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

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

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

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

WebWork 2使用OGNL這個(gè)強大的表達式語(yǔ)言,可以訪(fǎng)問(wèn)值棧。OGNL對集合和索引屬性的支持非常強大。

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

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

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

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

相對Struts 1ActionServlet API緊緊耦合的弱點(diǎn)來(lái)說(shuō),WebWorkAction則完全與Servlet API分離,因而該Action更容易測試。

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

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

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

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

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

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

 上面整個(gè)過(guò)程的數據流圖如圖1.8所示。

 

              1.8  WebWork的數據流圖

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

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

?       Action無(wú)需與Servlet API耦合,更容易測試

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

public class LoginAction implements Action

{

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

private final static String LOGINFAIL=”loginfail”;

 //Action封裝的兩個(gè)請求參數

private String password;

private String username;

//password請求參數對應的getter方法

public String getPassword()

{

return password;

}

//password請求參數對應的setter方法

public void setPassword(String password)

{

this.password = password;

                        }

//username請求參數對應的getter方法

public String getUsername()

{

return username;

               }

//username請求參數對應的setter方法

public void setUsername(String username)

{

this.username = username;

                        }

 //處理用戶(hù)請求的execute方法

public String execute() throws Exception

{

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

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

{

ActionContext ctx = ActionContext.getContext();

//將當前登錄的用戶(hù)名保存到Session

Map session = ctx.getSession();

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

return SUCCESS;

              }

else

{

return LOGINFAIL;

                }

         }

}

在上面的Action代碼中,我們看不到任何的Servlet API,當系統需要處理兩個(gè)請求參數:usernamepassword時(shí),Action并未通過(guò)HttpServletRequest對象來(lái)獲得請求參數,而是直接調用訪(fǎng)問(wèn)該Actionusernamepassword成員屬性——這兩個(gè)屬性由Action攔截器負責初始化,以用戶(hù)請求參數為其賦值。

即使Action中需要訪(fǎng)問(wèn)HTTP Session對象,依然沒(méi)有在代碼中直接出現HttpSession API,而是以一個(gè)Map對象代表了HTTP Session對象。

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

如果需要測試上面的Action代碼,測試用例的書(shū)寫(xiě)將非常容易,因為execute方法中沒(méi)有包含任何Servlet API,甚至沒(méi)有WebWorkAPI。

?       Action無(wú)需與WebWork耦合,代碼重用率高

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

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

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

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

?       支持更多的表現層技術(shù),有更好的適應性。

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

2.3  Struts 2起源

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

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

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

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

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

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

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

當然,對于傳統的Struts 1開(kāi)發(fā)者,Struts 2也提供了很好的向后兼容性,Struts 2可與Struts 1有機整合,從而保證Struts 1開(kāi)發(fā)者能平穩過(guò)渡到Struts 2。

3Struts 2體系介紹

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

3.1 Struts 2框架架構

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

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

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

  

    1.9  Struts 2的體系概圖

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

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

?       核心控制器FilterDispatcher根據請求決定調用合適的Action。

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

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

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

3.2 Struts 2的配置文件

Struts 2創(chuàng )建系統的Action代理時(shí),需要使用Struts 2的配置文件。

Struts 2的配置文件有兩份:

?       配置Actionstruts.xml文件。

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

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

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

<struts>

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

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

<!– 定義一個(gè)LogonAction,實(shí)現類(lèi)為lee.Logon –>

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

<!– 配置Action返回input時(shí)轉入/pages/Logon.jsp頁(yè)面 –>

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

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

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

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

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

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

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

</action>

<!– 定義LogoffAction,實(shí)現類(lèi)為lee.Logoff –>

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

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

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

</action>

</package>

</struts>

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

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

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

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

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

struts.devMode = false

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

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

3.3 Strut 2的標簽庫

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

通過(guò)使用Struts 2的標簽,開(kāi)發(fā)者可以最大限度地減少頁(yè)面代碼的書(shū)寫(xiě)。

看下面的JSP頁(yè)面的表單定義片段:

<!–  定義一個(gè)Action –>

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

<!– 下面定義三個(gè)表單域 –>

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

    年紀:<input type=”text” name=”age”/><br>

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

                                 <!– 定義一個(gè)輸出按鈕 –>

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

</form>

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

<!– 使用Struts 2標簽定義一個(gè)表單 –>

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

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

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

<s:textfield label=”年紀” name=”age”/>

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

<!– 定義一個(gè)提交按鈕 –>

<s:submit/>

</s:form>

則頁(yè)面代碼更加簡(jiǎn)潔,而且有更簡(jiǎn)單的錯誤輸出。圖1.10是上面使用Struts 2標簽執行數據校驗后的輸出。

1.10  使用Struts 2標簽的效果

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

3.4 Struts 2的控制器組件

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

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

下面是Struts 2Action代碼示例:

public class LoginAction

{

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

private String username;

//封裝用戶(hù)請求參數的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;

                        }

//處理用戶(hù)請求的execute方法

public String execute() throws Exception

{

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

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

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

{

return “success”;

                }

else

{

return “error”;

              }

       }

}

通過(guò)查看上面的Action代碼,發(fā)現該ActionWebWork中的Action更徹底,該Action無(wú)需實(shí)現任何父接口,無(wú)需繼承任何Struts 2基類(lèi),該Action類(lèi)完全是一個(gè)POJO(普通、傳統的Java對象),因此具有很好的復用性。

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

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

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

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

4Struts 2Struts 1的對比

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

Struts 1Struts 2在各方面的簡(jiǎn)要對比。

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

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

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

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

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

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

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

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

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

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

5WebWorkStruts 2對比

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

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

下面是Struts 2WebWork命名上存在改變(見(jiàn)表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成員名稱(chēng)的對應

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

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

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

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

6. 總 結

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

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

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久