J2EE架構(gòu)下系統(tǒng)設(shè)計模式
1.1? J2EE 應(yīng)用模型
J2EE
提供了一個企業(yè)級的計算模型和運(yùn)行環(huán)境用于開發(fā)和部署多層分布式結(jié)構(gòu)的應(yīng)用模型。該模型具有重用組件的能力、基于擴(kuò)展標(biāo)記語言
(XML)
的數(shù)據(jù)交換、統(tǒng)一的安全模式和靈活的事務(wù)控制。它通過提供企業(yè)計算環(huán)境所必需的各種服務(wù),使得部署在
J2EE
平臺上的多層應(yīng)用,可以實現(xiàn)高可用性、安全性、可擴(kuò)展性和可靠性。
1.1.1 J2EE框架
目前,Java 2平臺有3個版本,它們是適用于小型設(shè)備和智能卡的Java 2平臺Micro版(Java 2 Platform Micro Edition,J2ME)、適用于桌面系統(tǒng)的Java2平臺標(biāo)準(zhǔn)版(Java 2 Platform Standard Edition,J2SE)、適用于創(chuàng)建服務(wù)器應(yīng)用程序和服務(wù)的Java2平臺企業(yè)版(Java 2 Platform EnterpriseEdition,J2EE)。
J2EE
是一種利用
Java 2
平臺來簡化企業(yè)解決方案的開發(fā)、部署和管理相關(guān)的復(fù)雜問題的體系結(jié)構(gòu)。
J2EE
技術(shù)的基礎(chǔ)就是核心
Java
平臺或
Java2
平臺的標(biāo)準(zhǔn)版,
J2EE
不僅鞏固了標(biāo)準(zhǔn)版中的許多優(yōu)點,例如
"
編寫一次、隨處運(yùn)行
"
的特性、方便存取數(shù)據(jù)庫的
JDBC API
、
CORBA
技術(shù)以及能夠在
Internet
應(yīng)用中保護(hù)數(shù)據(jù)的安全模式等等,同時還提供了對
EJB
(
Enterprise JavaBeans
)、
Java Servlets API
、
JSP
(
Java Server Pages
)以及
XML
技術(shù)的全面支持。其最終目的就是成為一個能夠使企業(yè)開發(fā)者大幅縮短投放市場時間的體系結(jié)構(gòu)。
1.1.2
多層分布式結(jié)構(gòu)的應(yīng)用模型
J2EE
平臺采用一個多層次分布式的應(yīng)用模式。這意味著應(yīng)用邏輯根據(jù)功能被劃分成組件,組成
J2EE
應(yīng)用的不同應(yīng)用組件安裝在不同的服務(wù)器上,這種劃分是根據(jù)應(yīng)用組件屬于多層次
J2EE
環(huán)境中的哪一個層次來決定的。圖
1
展示了兩個多層次
J2EE
應(yīng)用劃分成在下面的表中描述的不同層次。圖
1
中表示的
J2EE
應(yīng)用部分代表了
J2EE
應(yīng)用組件。
?
運(yùn)行在客戶機(jī)器上的客戶層組件
?
運(yùn)行在
J2EE
服務(wù)器上的
Web
層組件
?
運(yùn)行在
J2EE
服務(wù)器上的業(yè)務(wù)層組件
?
運(yùn)行在
EIS
服務(wù)器上的企業(yè)信息系統(tǒng)層軟件
如圖
1
所示,
J2EE
應(yīng)用可以由三或四個層次組成,
J2EE
多層次應(yīng)用一般被認(rèn)為是三層應(yīng)用,因為它們是被分布在三個不同的地點:客戶端機(jī)器、
J2EE
服務(wù)器和數(shù)據(jù)庫或后端的傳統(tǒng)系統(tǒng)服務(wù)器。三層架構(gòu)應(yīng)用是對標(biāo)準(zhǔn)的客戶端
/
服務(wù)器應(yīng)用架構(gòu)的一種擴(kuò)展,即在客戶端應(yīng)用和后臺存儲之間增加一個多線程應(yīng)用服務(wù)器。?
?
?
?
?
?
?
?
?圖1:多層應(yīng)用
1.3 J2EE
架構(gòu)
通常,瘦客戶端多層次應(yīng)用是很難編寫的,因為它包括很多行非常難以理解的代碼,以處理交易和狀態(tài)管理,多線程,資源池管理,以及其他復(fù)雜的低層次細(xì)節(jié)問題。基于組件的、與平臺無關(guān)的
J2EE
應(yīng)用的開發(fā)是很容易的,因為業(yè)務(wù)邏輯被組織成可重復(fù)使用的組件,而且
J2EE
服務(wù)器以容器
(Container)
的形式為每種類型的組件提供后臺支持。由于你不必自己開發(fā)這些服務(wù),你可以專注于解決你面臨的業(yè)務(wù)問題。
1.3.1
容器(
container
)和服務(wù)
組件在部署時被安裝在容器之中,是組件和特定平臺底層功能之間的接口支持著組件。在
Web
,企業(yè)
Bean
或者應(yīng)用客戶端組件能夠被執(zhí)行以前,它必須被組裝到
J2EE
應(yīng)用里,并且被部署到它的容器里。組裝流程包括設(shè)定
J2EE
應(yīng)用中的每一個組件以及
J2EE
應(yīng)用本身在容器之中的設(shè)置。容器的設(shè)置個性化了
J2EE
服務(wù)器對每個組件的后臺支持,包括像安全性、交易管理、
Java
命名和目錄接口查詢,以及遠(yuǎn)程連接等等。這里是一些重點:
?
J2EE
安全模式,使你能夠配置
Web
組件或企業(yè)
Bean
,使系統(tǒng)資源只能被授權(quán)的用戶訪問。
?
J2EE
交易模式,使你能夠指定方法之間的關(guān)系,從而組成一個交易,這樣交易中的所有方法將被作為一個單元對待。
?
JNDI
查詢服務(wù),為企業(yè)中多種命名和目錄服務(wù)提供統(tǒng)一的接口,這樣應(yīng)用組件就可以訪問命名和目錄服務(wù)了。
?
J2EE
遠(yuǎn)程連接模式,管理客戶端和企業(yè)
Beans
之間的底層通訊。在企業(yè)
Bean
被創(chuàng)建后,客戶端調(diào)用它的方法,就像它在同一個虛擬機(jī)上一樣。
實際上,
J2EE
架構(gòu)提供可配置的服務(wù),意思是在同一個
J2EE
應(yīng)用中的應(yīng)用組件可以根據(jù)他們部署的位置不同,表現(xiàn)不同。一個企業(yè)
Bean
可以通過不同的安全設(shè)置,是它在一個生產(chǎn)系統(tǒng)中獲得一種層次的數(shù)據(jù)庫數(shù)據(jù)訪問,而在另一個生產(chǎn)系統(tǒng)中,則獲得另一種數(shù)據(jù)庫訪問權(quán)限。
容器還管理著不可配置服務(wù),如企業(yè)bean和Servlet的生命周期,數(shù)據(jù)庫連接資源池,數(shù)據(jù)持續(xù)性(persistence),以及J2EE API中描述的訪問J2EE平臺的API。
盡管數(shù)據(jù)持續(xù)性機(jī)制是一個不可配置服務(wù),
J2EE
架構(gòu)允許你在需要比缺省的容器管理的持續(xù)性機(jī)制更多的控制時,用你的企業(yè)
Bean
實現(xiàn)中的相應(yīng)的代碼覆蓋原有的容器管理的持續(xù)機(jī)制。例如,你可以使用
Bean
管理的持續(xù)性機(jī)制來實現(xiàn)你自己的搜索方法,或創(chuàng)建個性化的數(shù)據(jù)庫緩存。
1.3.2
容器類型
在部署過程之中,
J2EE
應(yīng)用組件被安裝在如下類型的
J2EE
容器中。本文中涉及的
J2EE
組件和容器參見圖
5
。
企業(yè)JavaBeans(EJB)容器,為J2EE應(yīng)用管理著所有的企業(yè)Beans。企業(yè)Bean和它們的容器運(yùn)行在J2EE服務(wù)器上。
Web
容器,為
J2EE
應(yīng)用管理著所有的
JSP
頁面和
Servlet
組件。
Web
組件和它們的容器運(yùn)行在
J2EE
服務(wù)器上。
應(yīng)用客戶端容器,為
J2EE
應(yīng)用管理著所有的應(yīng)用客戶端組件。應(yīng)用客戶端組件和它們的容器運(yùn)行在客戶端機(jī)器上。
applet
容器,是
Web
瀏覽器和
Java
插件的組合,運(yùn)行在客戶端機(jī)器上。
????????????????????
?
?
?
?
?
?
?
?
圖
5
:
J2EE
服務(wù)器和容器
1.3.3
包裝
J2EE
組件是單獨包裝的,為部署而捆綁到
J2EE
應(yīng)用中。每個組件,其相關(guān)的文件如
GIF
和
HTML
文件,或者服務(wù)器端應(yīng)用類,以及部署描述,被集成一個模塊并添加到
J2EE
應(yīng)用中。
J2EE
應(yīng)用是由一個或多個企業(yè)
Bean
,
Web
,或應(yīng)用客戶端組件模塊組成的。最終企業(yè)解決方案可以使用一個
J2EE
應(yīng)用或根據(jù)設(shè)計需要由兩個或更多的
J2EE
應(yīng)用組成。
一個
J2EE
應(yīng)用以及它的每一個模塊都有它自己的部署描述。部署描述是一個
XML
文本文件,帶有
.xml
后綴,描述組件的部署設(shè)置。一個企業(yè)
Bean
的部署描述,例如,聲明交易屬性,和企業(yè)
Bean
的安全認(rèn)證。由于部署描述的信息是可以聲明的,這樣它可以在無需修改
Bean
的源代碼的情況下,進(jìn)行修改。在運(yùn)行時,
J2EE
服務(wù)器讀取部署描述,并依次對組件進(jìn)行操作。
J2EE應(yīng)用以及相關(guān)的模塊是在一個Enterprise Archive(EAR)中發(fā)送的。EAR文件是一個標(biāo)準(zhǔn)的JAR文件,以.ear后綴結(jié)尾。在GUI版的J2EE SDK應(yīng)用部署工具集中,你先創(chuàng)建一個EAR文件,在添加JAR和WAR到EAR中。如果你使用命令行打包工具,則先創(chuàng)建JAR和WAR文件,然后創(chuàng)建EAR文件。J2EE SDK工具:
?
每個
EJB JAR
文件包含它的部署描述,相關(guān)文件和企業(yè)
Bean
的
.class
文件
?
每個應(yīng)用客戶端
JAR
包含它的部署描述,相關(guān)文件和應(yīng)用客戶端的
.class
文件
?
每個
WAR
文件包含它的部署描述,相關(guān)文件和
servlet
的
.class
文件以及
JSP
頁面的
.jsp
文件
使用模塊和
EAR
文件使使用一些相同的組件組裝多個不同的
J2EE
應(yīng)用成為可能。無需額外的編程,只是把不同的
J2EE
模塊組裝到
J2EE EAR
文件中。
1.4 J2EE API
Java 2
平臺標(biāo)準(zhǔn)版(
J2SE
)
SDK
在運(yùn)行
J2EE SDK
時是必需的,它為編寫
J2EE
組件提供核心
API
,核心開發(fā)工具,以及
Java
虛擬機(jī)。下面介紹科研管理系統(tǒng)中所涉及到的
API
。
1.4.1
企業(yè)
JavaBeans
技術(shù)
2.0
一個企業(yè)
Bean
是一段包含域和方法的代碼體,用于實現(xiàn)業(yè)務(wù)邏輯的一個模塊。你可以認(rèn)為企業(yè)
Bean
是一個構(gòu)建模塊,可以單獨使用或與其他企業(yè)
Beans
一起在
J2EE
服務(wù)器上執(zhí)行業(yè)務(wù)邏輯。
由三種類型的企業(yè)
Bean
:
Session Bean
,實體
Beans
,和消息驅(qū)動
Beans
,這些在業(yè)務(wù)組件中描述過。有了實體
Beans
,你無需編寫任何
SQL
代碼或直接使用
JDBC API
執(zhí)行數(shù)據(jù)庫訪問操作。
EJB
容器替你處理這些。當(dāng)然,如果你不管因為任何原因,覆蓋了卻省的容器管理持續(xù)性機(jī)制,你將需要使用
JDBC API
。同樣,如果你選用
Session Beans
訪問數(shù)據(jù)庫,你必須使用
JDBC API
。
1.4.2 JDBC 2.0 API
??????
JDBC
是為
java
語言定義的一個
SQL
調(diào)用級(
CLI
)界面,也就是說其中心在于執(zhí)行基本的
SQL
聲明和取回結(jié)果。在此基礎(chǔ)上可以定義更高層次的
API
,其中的接口包括直接將基本表與
JAVA
中的類相對應(yīng),提供更多的通用查詢的語義樹表示,以及
JAVA
語言的嵌入式
SQL
語法等。
1.4.3 Java Servlet
技術(shù)
2.3
Java Servlet
技術(shù)為你定義
HTTP
專用的
servlet
類。一個
Servlet
類擴(kuò)展了服務(wù)器的能力,這個服務(wù)器存放著應(yīng)用,而應(yīng)用是以請求
-
響應(yīng)編程模式被訪問的。盡管
Servlet
可以響應(yīng)任意形式的請求,但是它通常被用于擴(kuò)展
Web
服務(wù)器存放的應(yīng)用。
1.4.4 JavaServer Pages(JSP)
技術(shù)
1.2
JSP
頁面技術(shù)是你能夠在基于文本的文件中結(jié)合小段的
Java
編程語言代碼和靜態(tài)內(nèi)容。一個
JSP
頁面是一個基于文本的文件,它包含兩種類型的文本:靜態(tài)模板數(shù)據(jù),它可以表示為任何基于文本的格式,如
HTML
、
WML
和
XML
;
JSP
元素,決定這個頁面如何構(gòu)造動態(tài)內(nèi)容。
1.4.5 JavaMail
技術(shù)
1.2
很多互聯(lián)網(wǎng)應(yīng)用需要發(fā)送郵件進(jìn)行確認(rèn),所以
J2EE
平臺包含了與
JavaMail
服務(wù)提供商配合使用的
JavaMail API
,這樣,應(yīng)用組件可以使用它發(fā)送郵件。
JavaMail API
包含兩個部分:一個是應(yīng)用層接口,應(yīng)用組件使用它發(fā)送郵件;一個服務(wù)提供商接口。
1.5?MVC
設(shè)計模式
MVC設(shè)計模式起源于Smalltalk語言,它由以下三個部分組成:模型(model),視圖(view),控制器(Controller)。
Model
: 模型指的是真正完成任務(wù)的代碼,包含應(yīng)用系統(tǒng)的核心功
能表示一個應(yīng)用系統(tǒng)的數(shù)據(jù),并且包含訪問、維護(hù)和管理這些數(shù)據(jù)的邏輯。所有屬于應(yīng)用系統(tǒng)持久狀態(tài)的數(shù)據(jù)都應(yīng)該保存于模型對象里。模型提供的服務(wù)必須足夠適用于不同的終端。一個模型聚集了相關(guān)的數(shù)據(jù)和操作,以提供
一個詳細(xì)而精確的服務(wù)
;
這些被封裝在操作中的抽象事物的功能被模型化。一個模型的接口提供了訪問和更新模型狀態(tài),執(zhí)行封裝在模型中的復(fù)雜進(jìn)程
的方法。模型服務(wù)被控制器訪問,用于查詢或更改模型的狀態(tài)。當(dāng)模型狀態(tài)
發(fā)生變化時,模型會通報給視圖。對大多數(shù)
Web
應(yīng)用程序而言,功能比界面
感覺更重要。在模型同界面分離的情況下,代碼即可實現(xiàn)可管理性和可重用
性。例如,在一個保險應(yīng)用程序中,模型就是處理計算保險費(fèi)和同數(shù)據(jù)庫交互的那些業(yè)務(wù)代碼。模型通常也被稱作業(yè)務(wù)邏輯。
View
:
視圖表示模型的狀態(tài),是應(yīng)用系統(tǒng)的外觀,當(dāng)模型發(fā)生改變時,
視圖也將隨之改變,以維持系統(tǒng)數(shù)據(jù)的一致性。在
MVC
模式下,通常的設(shè)計
前提是界面任務(wù)較小。當(dāng)然視圖也應(yīng)該具有一定的功能性并遵守可用性的約
束,但視圖界面不應(yīng)當(dāng)處理數(shù)據(jù)。事實上,視圖的每一部分都只能包含采集
數(shù)據(jù)的邏輯,并把采集到的數(shù)據(jù)傳遞給設(shè)計模式中的其他組成部分進(jìn)行處
理。
Controller
:
控制器是聯(lián)系模型與視圖之間的紐帶,控制模型和視
圖之間的交互過程。它獲取并翻譯用戶輸入的動作,指定執(zhí)行該動作的模型,
或者根據(jù)用戶的輸入和執(zhí)行的結(jié)果來選擇下一個視圖。
MVC
通過建立一個
“
訂購
/
通知
”
協(xié)議來分離視圖和模型。視圖必須保證它的顯示正確地反映了模型的狀態(tài)。一旦模型的數(shù)據(jù)發(fā)生變化,模型將通知有關(guān)的視圖,每個視圖相應(yīng)地得到刷新自己的機(jī)會。這種方法可以讓一個模型提供不同的多個視圖表現(xiàn)形式,也能夠為一個模型創(chuàng)建新的視圖而無須重寫模型。
1.5.1 MVC
的優(yōu)點
(1)
因為視圖與模型分離,而且模型與視圖之間沒有直接依賴性,所以用戶界面可以同時顯示同一數(shù)據(jù)的多個視圖。例如,
Web
應(yīng)用程序中的多個頁面可以使用同一模型對象。變化一傳播機(jī)制可以確保所有相關(guān)的視圖及時
得到模型數(shù)據(jù)變化,從而使所有關(guān)聯(lián)的視圖和控制器做到行為同步。
(2)
視圖與控制器的可接插性,允許更換視圖和控制器對象,而且可以根據(jù)需求動態(tài)的打開或關(guān)閉、甚至在運(yùn)行期間進(jìn)行對象替換。
(3)
模型的可移植性。因為模型是獨立于視圖的,所以可以把一個模型獨立地移植到新的平臺工作。需要做的只是在新平臺上對視圖和控制器進(jìn)
行新的修改。
(4)
潛在的框架結(jié)構(gòu)。可以基于此模型建立應(yīng)用程序框架,不僅僅是
用在設(shè)計界面的設(shè)計中。
1.5.2 MVC
的缺點
(1)
增加了系統(tǒng)結(jié)構(gòu)和實現(xiàn)的復(fù)雜性。
MVC
模式引入了新的間接級別,
因此稍微增加了解決方案的復(fù)雜性。它還增加了用戶界面代碼的事件驅(qū)動特
性,調(diào)試用戶界面代碼會變得更加困難。
(2)
視圖與控制器間的過于緊密的連接。視圖與控制器是相互分離,但確實聯(lián)系緊密的部件,視圖沒有控制器的存在,其應(yīng)用是很有限的,反之亦然,這樣就妨礙了他們的獨立重用。
(3)
視圖對模型數(shù)據(jù)的低效率訪問。依據(jù)模型操作接口的不同,視圖可能需要多次調(diào)用才能獲得足夠的顯示數(shù)據(jù)
.
對未變化數(shù)據(jù)的不必要的頻繁訪
問,也將損害操作性能。
(4)
頻繁更新的成本。將模型與視圖分離并不意味著模型的開發(fā)人員可
以忽略視圖的特性。例如,如果模型發(fā)生頻繁更改,則它可能向視圖發(fā)出大
量更新請求。一些視圖
(
如圖形顯示
)
的顯示可能需要一定時間。因此,視
圖可能滯后于更新請求。因此,在對模型進(jìn)行編碼時牢記視圖是很重要的。
例如,模型可以將多個更新作為單個通知發(fā)送到視圖。
??????????????????????? ???????模型?????
??????????? 查詢狀態(tài)
???????????????????? 向視圖通知模型????????? 在模型的公共
?????????????????????? 狀態(tài)中的改變??????????????????? API中調(diào)用方法
?
??? 視圖????? ???選擇視圖?????????????? 控制器
????????????用戶動作/命令
????????????????????? 方法調(diào)用
????????事件
圖6???? MVC的體系結(jié)構(gòu)
1.6 Struts對MVC實現(xiàn)
模型(
The Model
)
Struts框架沒有提供特定的模型組件。
視圖(
The View
)
Struts
框架中
視圖組件對應(yīng)于一個簡單的
JSP
文件,這個
JSP
文件包含了
Struts
定義的標(biāo)簽,幾個
JSP
的標(biāo)簽是
JSP
文件中的重點。這些標(biāo)簽在
Struts
框架中定義,它使
struts
應(yīng)用項目和控制器之間實現(xiàn)松耦合。
控制器(
The Controller
)
控制器是Struts框架中的中樞,它由
org.apache.struts.action.ActionServlet
這個servlet來貫徹和執(zhí)行的。這個
org.apache.struts.action.ActionServlet
接收所有客戶端的請求,并把請求委派到指定的Action類(用戶擴(kuò)展自
org.apache.struts.action
)。ActionServlet委派請求是基于客戶端傳入的URI。一旦Action類完成處理,ActionServlet根據(jù)Action返回的鍵值來決定在什么視圖中顯示Action的類處理結(jié)果。ActionServlet類似于一個創(chuàng)建Action對象的工廠,由Action對象去執(zhí)行應(yīng)用中實際的業(yè)務(wù)邏輯。控制器是Struts框架中最重要的部分。
1.6.1 Struts的運(yùn)行過程
下面是一幅和MVC模式對應(yīng)的STRUTS框架圖
?視圖(view1)???????????????????????????????????
????????????????????????????????????????????? Action1
???????????????????????????????????????????????????
???? ?????????????????????????????????????????Action2
?????????????????? ActionServlet????????????? Action3
???????????????????? (控制器)
????????????????????????????????????????????? Action4
??????????????????????????????????????????????????
視圖(view2)???????? ?????????????????????????????????模型(Model)
?
????? 圖7?STRUTS框架圖
圖7是Struts框架下應(yīng)用程序請求流通過的路徑。這個處理過程由5個基本的步驟組成。
下面是處理步驟的描述。
1.由顯示視圖產(chǎn)生一個請求。
2.?請求被ActionServlet(控制器)接收,它在struts-config.xml文件中尋找請求的URI,找到對應(yīng)的Action類后,Action類執(zhí)行相應(yīng)的業(yè)務(wù)邏輯。
3.?Action類執(zhí)行建立在模型組件基礎(chǔ)上的業(yè)務(wù)邏輯,模型組件是和應(yīng)用程序關(guān)聯(lián)的。
4.?一旦Action類處理完業(yè)務(wù)邏輯,它把控制權(quán)返回給ActionServlet。,Action類提供一個鍵值作為返回的一部分,它指明了處理的結(jié)果。ActionServlet使用這個鍵值來決定在什么視圖中顯示Action的類處理結(jié)果。
5.?當(dāng)ActionServlet把Action類的處理結(jié)果傳送到指定的視圖中,請求的過程也就完成了。
?
???????????????? HttpServlet???????????????????? ?????????????????????FrowardConfig
?? <<front controller>>
org.apache.struts.action.ActionServlet??????????????????? org.apache.struts.action.ActionForWard
?
?
?
??<<dispatcher>>???????????????????????????????????????????????????? ActionConfig
?org.apache.struts.action.RequestProcessor????????????????? org.apache.struts.action.ActionMapping
?
?
????????????????????? Serializable
?????????? <<view helper>>??????????????????????????????? <<request handler>>
?? org.apache.struts.action.ActionForm??????????? ???????????????????org.apache.struts.action.Action
?
圖8?Struts中MVC實現(xiàn)
?
圖8中各個類的語義
1.?ActionServlet類:實現(xiàn)控制器,Struts必需的配置在ActionServlet.init()方法中加載。ActionServlet將所有的輸入請求委托給RequestProcessor.
2.?RequestProcessor類:分配器,所有輸入的請求都被控制器委托給分配器(dispatcher).
3. ActionForm類:存儲表單數(shù)據(jù),由ActionForm派生出來的對象用于存儲請求對象中的參數(shù),因此它們和用戶是緊密耦合的。
4. ActionForward類:ActionForward對象是配置對象。這些配置對象有唯一的標(biāo)識符,以使它們根據(jù)有意義的名稱進(jìn)行尋找。ActionForward對象封裝提交的URL路徑,它被請求處理程序用來標(biāo)識目標(biāo)視圖。
5. ActionMapping類:它提供了引入的請求和相應(yīng)的請求處理程序之間的映射。
6.Action類:請求處理程序。Action類的子類作為適配器用于引入的請求和模型之間。Action類的子類是為每個請求單獨創(chuàng)建的。Action的基類提供了訪問與框架相關(guān)的資源的公共函數(shù),以及保存由它的子類的exectue(…)方法進(jìn)行檢查而得到錯誤的方法。
1.6.2?Struts的主要組件:
1.6.2.1 控制器對象
控制器語義有ActionServlet。控制器語義提供了處理所有客戶請求的中心位置。這就為控制器層提供了一個清楚的工作分配情況,控制器層主要的工作是處理試圖和導(dǎo)航管理、將模型訪問和操作交給有特定請求的請求處理程序(Command對象[Gof])。所有引入的請求被映射到部署描述符的中心控制器上。
1.6.2.2 分配器對象
RequestProcessor作為一個分配器運(yùn)行,并通過實例化(或重用)一個請求處理和對應(yīng)的表單bean來處理客戶機(jī)請求。創(chuàng)建的錯誤或是表單bean和請求處理程序拋出的異常(由RequestProcessor處理),影響了RequestProcessor的視圖管理功能。表單bean幫助RequestProcessor存儲表單數(shù)據(jù)和分段傳輸視圖需要的中間模型數(shù)據(jù),RequestProcessor使用<action>聲明實例化特定請求的請求處理程序。
1.6.2.3請求處理程序
Action類的子類作為適配器用于引入的請求和模型之間。請求最初由RequestProcessor截獲,RequestProcessor則實例化一個對應(yīng)的請求處理程序。這個從Action類繼承而來的對象(也稱為請求處理程序)是為每個請求而特別創(chuàng)建的。客戶機(jī)請求封裝請求URI中所需的動作作為servlet路徑,該路徑信息隨后有分配器(RequestProcessor)提取,從而創(chuàng)建相應(yīng)的請求處理程序來處理程序?qū)嵗C钅J綄?/span>URI從請求處理程序中分離出來。
1.6.3?Struts的配置文件struts-config.xml
Struts 的核心是控制器ActionServlet,而ActionServlet的核心是配置文件struts-config.xml,該配置文件的主要作用是建立控制器與模型之間的聯(lián)系。它描述了控制器將客戶請求映射到對應(yīng)處理的法則,同時還定義了用戶輸入數(shù)據(jù)與ActionFor。組件的對應(yīng)映射關(guān)系。此外,該配置文件的另一個作用是將邏輯名映射到物理路徑,使得物理路徑與程序路徑無關(guān),整個系統(tǒng)導(dǎo)航使用邏輯名在struts-config.xml中完成。
這種在配 置文件中完成業(yè)務(wù)邏輯控制的方法主要有以下幾個優(yōu)點:首先,應(yīng)用的所有頁面的導(dǎo)航定義都集中在一個分等級的文本文件中,通過此配置文件即可迅速把握整個系統(tǒng)的脈絡(luò);第二,網(wǎng)頁設(shè)計人員在修改網(wǎng)頁時無需遍歷Java代碼來理解應(yīng)用的業(yè)務(wù)邏輯,而當(dāng)業(yè)務(wù)邏輯發(fā)生改變時,業(yè)務(wù)邏輯開發(fā)者也只需在struts-config.xml中做出相應(yīng)的調(diào)整和修改,而無需重新編譯代碼。在大型的Web應(yīng)用系統(tǒng)中,這種管理頁面邏輯的方式無論是在系統(tǒng)前期的開發(fā)過程,還是后期的維護(hù)與升級階段都顯示出了方便性和有效性。
struts-config.xml的正文部份由八個元素組成,下面將對系統(tǒng)中涉及的元素的功能與使用方法舉例闡明。
1.6.3.1 定義ActionForm
ActionServlet使用ActionForm來保存請求參數(shù),這些Bean的屬性名稱與HTTP請求參數(shù)中的名稱相對應(yīng),控制器將請求參數(shù)傳遞到ActionFormBean的實例中,然后將這個實例傳送到Action類。Struts的配置文件struts-config.xml提供了一個<form-beans>元素用于統(tǒng)一管理系統(tǒng)中所有的ActionForm Bean。每個ActionForm Bean都由一個相應(yīng)的<form-bean>元素創(chuàng)建。在運(yùn)行時,控制器通過調(diào)用適當(dāng)?shù)腁ctionForm Bean來確定被創(chuàng)建的ActionForm對象及特性。下面是項目中一個針對常規(guī)ActionForm的<form-bean>元素配置:
<form-beans>
<form-bean name="userInfoForm" ???? ???? ?type="aiai.keyan.manage.user_Manage.pursuerInfoBean" />
</form-beans>
其中,屬性name是表單bean在相關(guān)作用域的名稱,它用于將ActionFormBean與ActionMapping進(jìn)行關(guān)聯(lián);而屬性type是類的完全限定名。
1.6.3.2 定義全局轉(zhuǎn)發(fā)
在常見的Web應(yīng)用中,多數(shù)URI都與應(yīng)用中的物理文件直接映射,這在應(yīng)用開發(fā)的初級階段顯得較為容易。但是,在應(yīng)用開發(fā)的后期或維護(hù)階段,應(yīng)用的邏輯通常會發(fā)生改變,這時就必須更新整個應(yīng)用,如果遺漏了某部分,就會產(chǎn)生“異常更新”。這一點給應(yīng)用的后期開發(fā)者和維護(hù)人員造成了不小的困難。為了解決這一難題,在Struts應(yīng)用中,開發(fā)人員將邏輯名映射到物理地址,在應(yīng)用中使用邏輯名實現(xiàn)系統(tǒng)導(dǎo)航,這就使得應(yīng)用的物理地址與程序地址無關(guān)。而元素<global-forwards>就是用于實現(xiàn)這個功能。這個元素可以包含任意個<forward/>子元素,每一個子元素對應(yīng)一個邏輯名與一個物理地址的映射。當(dāng)系統(tǒng)的邏輯發(fā)生改變時,開發(fā)人員只需修改相應(yīng)<forward/>中的映射關(guān)系即可。如下所示:
<global-forwards>
<forward name="forStep1"
path="/researching/datainput/step1.jsp" />
</global-forwards>
上述代碼是項目的配置文件中的一部分。其中,屬性name表示全局轉(zhuǎn)發(fā)的邏輯名,path表示目標(biāo)URI的物理路徑。除了可 以 在<global-forwards>元素中部署全局轉(zhuǎn)發(fā)外,開發(fā)人員除還可以在<action>元素中部署局部轉(zhuǎn)發(fā), 局部轉(zhuǎn)發(fā)僅針對對應(yīng)的ActionMapping有效。
1.6.3.3 定義Action映射
<Action -Mapping>元素的作用在于幫助開發(fā)人員進(jìn)行框架內(nèi)部的流程控制。該元素可以包含任意個<action />子元素。每一個子元素將一個請求URI路徑映射到對應(yīng)的Action類,并且將Action類與對應(yīng)ActionForm bean相關(guān)聯(lián)。ActionServlet在內(nèi)部使用這些映射,并將控制轉(zhuǎn)移到特定的Action類實例。所有Action類使用perform()方法實現(xiàn)特定的業(yè)務(wù)邏輯,然后返回一個ActionForward對象,其中包括響應(yīng)轉(zhuǎn)發(fā)的目標(biāo)資源名稱。下列代碼截取自項目的配置文件:
<action-mappings>
<action name="userInfoForm" ?type="aiai.keyan.manage.user_Manage.Struts.userInfoAction" validate="true"
input="/menage/user/register1.jsp"
scope="request" path="/register1" />
</action-mappings>
其中子元素<action>的屬性path表示Action類的相對路徑,name表示與指定操作關(guān)聯(lián)的Action Bean的名稱,type表示連接到本映射的Action類的全稱,scope表示與指定Action對應(yīng)的ActionForm Bean的作用域,input表示輸入表單的路徑和發(fā)生輸入錯誤時系統(tǒng)應(yīng)返回的頁面。在<action-mappings>元素中還可以使用<forward>子元素定義資源的邏輯名稱,該資源是Action類的響應(yīng)要轉(zhuǎn)發(fā)的目標(biāo)。其中<forward>的屬性name表示Action類訪問ActionForward時所用的邏輯名,path表示響應(yīng)轉(zhuǎn)發(fā)的目標(biāo)資源的路徑。
1.6.4 Struts的自定義標(biāo)記庫
Struts 提供了一組可擴(kuò)展的自定義標(biāo)記庫(Taglib),采用這些標(biāo)記庫,可以幫助開發(fā)人員簡化創(chuàng)建用戶界面的過程。目前 Struts提供了四種基本自定義Taglib以及兩種附加Taglib .
struts-bean taglib:不僅包含可以在訪問bean和bean屬性時使用的標(biāo)記,還包含一些用于消息顯示的標(biāo)記。
struts-html taglib:不僅包含用于創(chuàng)建Struts輸入表單的標(biāo)記,而且包含其它通常用來創(chuàng)建動態(tài)HTML用戶界面或表格的標(biāo)記。
struts-logic taglib:該庫所包含的標(biāo)記通常用于管理輸出文本的條件生成、循環(huán)使用對象集合以重復(fù)生成輸出文本以及應(yīng)用程序流管理。
struts-template taglib:該庫包含的標(biāo)記可用作創(chuàng)建動態(tài)JSP模板,所有采用同一模板的JSP頁面都擁有一個公共的外觀或共同的格式。
T iles 插件:除了替代Template的基本模板功能外,還增加了布局定義、虛擬頁面定義和動態(tài)頁面生成等功能。Tiles強(qiáng)大的模板功能能夠使頁面獲得最大的重用性和靈活性,此外,結(jié)合Tiles配置文件中的頁面定義和Action的轉(zhuǎn)發(fā)邏輯(即將一個Action轉(zhuǎn)發(fā)到一個在Tile:配置文件中定義的虛擬頁面),可以減少頁面的數(shù)量,從而簡化JSP開發(fā)。
Nested:該標(biāo)記庫的作用在于讓上述的基本Struts自定義標(biāo)記庫的功能能夠嵌套應(yīng)用于上下文,發(fā)揮更大的作用。
?
2.7?WEB服務(wù)器的搭建與集成
2.7.1 jsp,Serlvet容器Tomcat
????? Tomcat是一個免費(fèi)的開源的Serlvet容器,它是Apache基金會的Jakarta項目中的一個核心項目,由Apache,Sun和其它一些公司及個人共同開發(fā)而成。由于有了Sun的參與和支持,最新的Servlet和Jsp規(guī)范總能在Tomcat中得到體現(xiàn)。
?? 由于Java的跨平臺特性,基于Java的Tomcat也具有跨平臺性。與傳統(tǒng)的桌面應(yīng)用程序不同,Tomcat中的應(yīng)用程序是一個WAR(Web?Archive)文件。WAR是Sun提出的一種Web應(yīng)用程序格式,與JAR類似,也是許多文件的一個壓縮包。這個包中的文件按一定目錄結(jié)構(gòu)來組織:通常其根目錄下包含有Html和Jsp文件或者包含這兩種文件的目錄,另外還會有一個WEB-INF目錄,這個目錄很重要。通常在WEB-INF目錄下有一個web.xml文件和一個classes目錄,web.xml是這個應(yīng)用的配置文件,而classes目錄下則包含編譯好的Servlet類和Jsp或Servlet所依賴的其它類(如JavaBean)。通常這些所依賴的類也可以打包成JAR放到WEB-INF下的lib目錄下,當(dāng)然也可以放到系統(tǒng)的CLASSPATH中,但那樣移植和管理起來不方便。
?? 在Tomcat中,應(yīng)用程序的部署很簡單,你只需WAR放到Tomcat的webapp目錄下,Tomcat會自動檢測到這個文件,并將其解壓。在瀏覽器中訪問這個應(yīng)用的Jsp時,通常第一次會很慢,因為Tomcat要將Jsp轉(zhuǎn)化為Servlet文件,然后編譯。編譯以后,訪問將會很快。另外Tomcat也提供了一個應(yīng)用:manager,訪問這個應(yīng)用需要用戶名和密碼,用戶名和密碼存儲在一個xml文件中。通過這個應(yīng)用,輔助于Ftp,你可以在遠(yuǎn)程通過Web部署和撤銷應(yīng)用。當(dāng)然本地也可以。?Tomcat不僅僅是一個Servlet容器,它也具有傳統(tǒng)的Web服務(wù)器的功能:處理Html頁面。但是與Apache相比,它的處理靜態(tài)Html的能力就不如Apache。我們可以將Tomcat和Apache集成到一塊,讓Apache處理靜態(tài)Html,而Tomcat處理Jsp和Servlet。這種集成只需要修改一下Apache和Tomcat的配置文件即可。
?? 另外,Tomcat提供Realm支持。Realm類似于Unix里面的group。在Unix中,一個group對應(yīng)著系統(tǒng)的一定資源,某個group不能訪問不屬于它的資源。Tomcat用Realm來對不同的應(yīng)用(類似系統(tǒng)資源)賦給不同的用戶(類似group)。沒有權(quán)限的用戶則不能訪問這個應(yīng)用。Tomcat提供三種Realm,1:JDBCRealm,這個Realm將用戶信息存在數(shù)據(jù)庫里,通過JDBC獲得用戶信息來進(jìn)行驗證。2:JNDIRealm,用戶信息存在基于LDAP的服務(wù)器里,通過JNDI獲取用戶信息。3:MemoryRealm,用戶信息存在一個xml文件里面,上面講的manager應(yīng)用驗證用戶時即使用此種Realm。通過Realm我們可以方便地對訪問某個應(yīng)用的客戶進(jìn)行驗證。
?? 在Tomcat中,可以利用Servlet2.3提供的事件監(jiān)聽器功能,來對Application或者Session實行監(jiān)聽。Tomcat也提供其它的一些特征,如與SSL集成到一塊,實現(xiàn)安全傳輸。還有Tomcat也提供JNDI支持,這與那些J2EE應(yīng)用服務(wù)器提供的是一致的。說到這里要介紹一下通常所說的應(yīng)用服務(wù)器(如WebLogic)與Tomcat有何區(qū)別。應(yīng)用服務(wù)器提供更多的J2EE特征,如EJB,JMS,JAAS等,同時也支持Jsp和Servlet。而Tomcat則功能沒有那么強(qiáng)大,它不提供EJB等支持。但如果與JBoss(一個開源的應(yīng)用服務(wù)器)集成到一塊,則可以實現(xiàn)J2EE的全部功能。既然應(yīng)用服務(wù)器具有Tomcat的功能,那么Tomcat有沒有存在的必要呢?事實上,在很多中小應(yīng)用不需要采用EJB等技術(shù),Jsp和Servlet已經(jīng)足夠,這時如果用應(yīng)用服務(wù)器就有些浪費(fèi)了。而Tomcat短小精悍,配置方便,能滿足我們的需求,這種情況下我們自然會選擇Tomcat。
???? Tomcat也可以與其它一些軟件集成起來實現(xiàn)更多的功能。如與上面提到的JBoss集成起來開發(fā)EJB,與Cocoon(Apache的另外一個項目)集成起來開發(fā)基于Xml的應(yīng)用,與OpenJMS 集成起來開發(fā)JMS應(yīng)用,除了我們提到的這幾種,可以與Tomcat集成的軟件還有很多。
配置Tomcat虛擬目錄,為了使得Tomcat即可以實時對開發(fā)工具的修改進(jìn)行監(jiān)測,以達(dá)到與開發(fā)工具實時同步數(shù)據(jù)。可以在不重啟服務(wù)器的情況下對項目進(jìn)行修改。這是非常重要的由于在一臺服務(wù)器上可能運(yùn)行這不止一個的WEB項目,在新加項目時不可能讓服務(wù)器重啟,因此必須配置虛擬目錄。在{TOMCAT_HOME}/conf/server.xml中的<Host></Host>之間加上
<Context path="dir1"
docBase="D:\web"??
reloadable="true" crossContext="true" >
</Context >
其中:
path: web應(yīng)用的context路徑。catalina將每個URL的起始和context path進(jìn)行比較,選擇合適的web應(yīng)用處理該請求。特定Host下的context path必須是惟一的。如果context path為空字符串(""),這個context是所屬Host的缺省web應(yīng)用,用來處理不能匹配任何context path的請求。
DocBase:該web應(yīng)用的文檔基準(zhǔn)目錄(Document Base,也稱為Context Root),或者是WAR文件的路徑。可以使用絕對路徑,也可以使用相對于context所屬的Host的appBase路徑。
Reloadable: 如果希望Catalina監(jiān)視/WEB-INF/classes/和/WEB-INF/lib下面的類是否發(fā)生變化,在發(fā)生變化的時候自動重載web application,設(shè)為true。這個特征在開發(fā)階段很有用,但也大大增加了服務(wù)器的開銷。因此,在發(fā)布以后,不推薦使用。但是,你可以使用Manager應(yīng)用在必要的時候觸發(fā)應(yīng)用的重載。
CrossContext:如果想在應(yīng)用內(nèi)調(diào)用ServletContext.getContext()來返回在該虛擬主機(jī)上運(yùn)行的其他web application的request dispatcher,設(shè)為true。在安全性很重要的環(huán)境中,設(shè)為false,使得getContext()總是返回null。缺省值為false。
2.7.2 HTTP服務(wù)器Apache2.0
Apache HTTP服務(wù)器被設(shè)計為一個強(qiáng)大、靈活的能夠在多種平臺上及不同的環(huán)境下工作的服務(wù)器。不同的平臺和不同的環(huán)境經(jīng)常產(chǎn)生不同的需求,或是會為了達(dá)到同樣的最佳效果而采用不同的方法。Apache憑借它的模塊設(shè)計很好的適應(yīng)了大量不同的環(huán)境。這一設(shè)計使得網(wǎng)站管理員能夠在編譯時和運(yùn)行時憑借載入不同的模塊來決定服務(wù)器的不同附加功能。
Apache可以在混合多進(jìn)程、多線程模式下運(yùn)行,使很多(但不是全部的)配置的可擴(kuò)縮性得到改善。Apache2.0重寫了原來的編譯系統(tǒng),現(xiàn)在是基于autoconf和libtool的,使得Apache的配置系統(tǒng)與其他軟件包更加相似。Apache 2.0在諸如BeOS,OS/2和Windows等非Unix平臺上有了更好的速度和穩(wěn)定性。 隨著平臺特定的multi-processing modules(MPMs)和 Apache Portable Runtime (APR)的引入,Apache在這些平臺上的指令由它們本地的API指令實現(xiàn)。 避免了以往使用POSIX模擬層造成的bug和性能低下。
2.7.3 Tomcat與Apache的整合
整合Apache有兩個目的
1. 把靜態(tài)和動態(tài)的內(nèi)容分別有兩個不同的服務(wù)器承擔(dān)
2.達(dá)到簡單的負(fù)載均衡
修改Uri mapping的內(nèi)容即可實現(xiàn)分流
如:
# Uri mapping?
[uri:/*.*]?
改成
# Uri mapping
[uri:/*.do]
[uri:/*.jsp]
第一步 把mod_jk_2.0.47.dll拷貝到{Apache}\modules文件夾中。
第二步 在{TOMCAT_HOME}\conf中新建一個workers.properties文件內(nèi)容如下
#####--begin--########
?workers.tomcat_home={TOMCAT_HOME}?#讓mod_jk模塊知道Tomcat
?workers.java_home={JAVA_HOME}?????? #讓mod_jk模塊知道j2sdk
?ps=\
?worker.list=ajp13?????????????????????? #模塊版本
?worker.ajp13.port=8009?????????? ???????#工作端口
?worker.ajp13.host=localhost?????????????? #主機(jī)名稱
worker.ajp13.type=ajp13???????????????? #類型
?worker.ajp13.lbfactor=1????????????????? #代理數(shù)
######---end---#######
第三步?打開{Apache}\conf\httpd.conf 在文件末尾添加如下內(nèi)容
########-beging--########
<VirtualHost?localhost>????????????????????? ??????? ??????? ????????
ServerAdmin?hua@mzh.com??????????????? #apache注冊的信息
DocumentRoot?D:\Web ??????? ??????? ????
#與tomcat虛擬目錄中docBase相同
ServerName?localhost??????? ??????????????? #主機(jī)名稱
ErrorLog?logs/robornet_home_log.txt??? #日志?? ??????? ??????? ????????
CustomLog?logs/robornet_Custom_log.txt?common?????????????????
JkMount /* ajp13???????? #目錄中的以下文件由tomcat處理????????????????????????
JkMount /*.jsp ajp13???
JkMount /*.do ajp13???????????????????????????????????????????
JkMount /*.gif ajp13?
JkMount /*.jpg ajp13???
JkMount /*.css ajp13
JkMount /*.js ajp13????
</VirtualHost>?
########-end--########
?
########-beging--########
LoadModule jk_module modules/mod_jk_2.0.47.dll
#裝載模塊,用于處理連接(對上一行的注釋,下同)
JkWorkersFile "{ TOMCAT_HOME }/conf/workers.properties"
#設(shè)置模塊的工作文件
JkLogFile "{ TOMCAT_HOME }/logs/mod_jk2.log"
?#設(shè)置模塊工作的日志文件,Tocmat啟動時會自建
JkLogLevel info
######---end---###########
其中:TOMCAT_HOME是tomcat的路徑
????????????? ?? JAVA_HOME是j2sdk的路徑
????????????? ?? Apache是Apache路徑
posted on 2007-03-09 00:52 金家寶 閱讀(2371) 評論(0) 編輯 收藏 所屬分類: J2EE概念理論性文摘