摘要:提出了一個基于Struts的軟件系統(tǒng)框架WEF(WrappingEJBFramework),該框架采用隱式實現(xiàn)服務定位,提高了JNDI服務的檢索速度;強制使用ObjectValue降低網(wǎng)絡傳輸?shù)拇鷥r;采用配置文件等技術(shù)改善EJB的執(zhí)行靈活性。對所提出的WEF的表示層和業(yè)務層進行了詳細分析,并對WEF的核心模塊的實現(xiàn)進行了描述,最后通過圖書館管理系統(tǒng)給出了WEF的一個實現(xiàn)。通過WEF的包裝,EJB組件的調(diào)用將變得更加簡潔,這有助于提高信息系統(tǒng)軟件的開發(fā)效率,減小維護代價。
關(guān)鍵詞:EJB;J2EE;Struts框架
中圖法分類號:TP3315文獻標識碼:A
文章編號:1001-3695(2006)09-0146-03
1引言
J2EE規(guī)范為企業(yè)級軟件開發(fā)提供了一個非常理想的平臺[1~3]。J2EE的核心是EJB(EnterpriseJaveBeans,EJB)。EJB在分布式、面向?qū)ο蟮钠髽I(yè)級應用系統(tǒng)開發(fā)過程中可以提高系統(tǒng)的可復用性和可維護性[4,5,7],但是EJB在實際使用時調(diào)用煩瑣,缺乏靈活性[6],原因主要有以下幾個方面:
(1)EJB是分布式對象,引用EJB需要通過JNDI服務,需要耗費一定的時間;
(2)EJB是建立在Java的RMIIIOP機制上的遠程對象,需要通過網(wǎng)絡傳遞許多附加信息;
(3)EJB所依賴的通信端口并非標準的系統(tǒng)端口,在某些企業(yè)應用中會面臨安全策略的挑戰(zhàn),如果部署的目標機由于種種原因無法開放EJB端口,EJB就無法在這種環(huán)境中使用;
(4)由于EJB是分布式對象,每個EJB方法都會聲明拋出一系列的遠程異常,而Java語言的異常傳播機制又需要每個所涉及的函數(shù)要么鏈式拋出異常,要么捕獲異常,大大降低了源代碼的可讀性,也增大了程序員犯邏輯錯誤的可能性。
針對以上問題,提出了一個應用軟件開發(fā)框架WEF(WrappingEJBFramework)以提高EJB的執(zhí)行效率和靈活性。WEF的基本設計思路是:
(1)隱式實現(xiàn)ServiceLocator模式,提高JNDI服務的檢索速度;
(2)在調(diào)用中強制使用ObjectValue模式,降低網(wǎng)絡傳輸和序列化對象的代價;
(3)提供服務接口和協(xié)議無關(guān)化的手段,突破端口安全策略的限制;
(4)提供聲明性異常處理體系,使得異常處理代碼被配置文件取代,只需在配置文件中聲明異常處理方法而不需編寫異常捕捉和拋出的代碼。
2WEF的設計
2.1WEF的表示層部分
WEF的表示層部分是WEF提供給WEF所包裝的EJB服務的調(diào)用者的,其主要功能就是定位和調(diào)用EJB服務。
為了使得切換調(diào)用協(xié)議不影響客戶端代碼,這里使用了一個工廠模式以避免客戶端代碼中直接引用特定的協(xié)議適配器對象,如圖1所示。
在圖1中,WEFClient是WEF表示層暴露給用戶的一個類,它擁有一個sendRequest方法,這個方法以用戶的IRequest對象為參數(shù),以業(yè)務層的IResponse對象為返回值(當通過JMS調(diào)用業(yè)務層服務時返回值為Null)。每個協(xié)議適配器都實現(xiàn)了IAdapter接口,這個接口有兩個方法:Execute和Config。Execute是發(fā)送數(shù)據(jù)的方法,當WEFClient被客戶調(diào)用發(fā)送請求時,它就把IRequest的完全限定名傳給AdapterFactory,以得到一個IAdapter實現(xiàn),然后WEFClient就把IRequest對象交給它發(fā)送。至于IAdapter實現(xiàn)具體是哪一種由AdapterFactory負責決定。它會在自己的配置信息中查找當前請求有沒有定義發(fā)送協(xié)議,如果定義了,就返回所定義的發(fā)送協(xié)議的適配器實現(xiàn);如果沒有找到,就返回默認的發(fā)送協(xié)議適配器實現(xiàn)(RMIIIOP適配器)。Config是配置適配器的方法,因為像RMIIIOP適配器需要知道業(yè)務層RMI代理的JNDI名稱才可以發(fā)送數(shù)據(jù),而HTTP適配器也需要知道服務端Servlet的URL地址等。這些信息需要在發(fā)送數(shù)據(jù)之前得到設置。
由于在WEF表示層提供了多種消息傳遞協(xié)議,當用戶通過WEFClinent類調(diào)用業(yè)務層服務時,可以不必考慮所采用的傳輸協(xié)議的類型,而在配置文件中預先設置協(xié)議類型,這樣在調(diào)用EJB時不必獲取遠程接口,提高了執(zhí)行效率。
在構(gòu)造調(diào)用參數(shù)時,WEF要求用戶實現(xiàn)WEF提供的IRequest和IResponse接口,并且在實現(xiàn)類中只包含調(diào)用所需的數(shù)據(jù)和數(shù)據(jù)的存取方法,也就是構(gòu)造值對象以減小網(wǎng)絡負擔。
WEF提供了一個基于Struts框架的擴展,通過這個擴展,用戶在調(diào)用業(yè)務層服務時不必對可能的異常進行編碼,而是在WEF提供的配置文件中聲明如何處理某類異常,這樣不但大大簡化了代碼的編寫,也提高了代碼的重用率。
2.2WEF的業(yè)務層部分
WEF的主體在業(yè)務邏輯層,這一層需要EJB容器、JNDI服務器等中間件服務器。如果要使用HTTP代理,需要有Servlet容器;如果要使用SOAP代理,還需要有Axis服務器。
從功能上講,WEF業(yè)務邏輯層可以分為三個部分:
(1)輔助模塊,包括啟動管理、會話管理、日志管理、監(jiān)控管理、異常系統(tǒng)等;
(2)處理器引擎,包裝實現(xiàn)業(yè)務邏輯EJB的地方,為實現(xiàn)業(yè)務邏輯的EJB提供前置和后置處理器以及查詢定位調(diào)用服務;
(3)代理層,提供WEF協(xié)議無關(guān)化的功能,負責將協(xié)議相關(guān)的數(shù)據(jù)格式恢復為用戶定義的輸入數(shù)據(jù),提交給WEF進行處理,再把返回數(shù)據(jù)根據(jù)原始格式進行包裝,返回給表示層。
圖2是WEF業(yè)務層部分的示意圖。其中,ProcessorLocator實現(xiàn)了ServiceLocator,使得在調(diào)用EJB時不必每次調(diào)用JNDI服務,可以使用ProcessorLocator緩存的內(nèi)容,提高了EJB的執(zhí)行效率。
3WEF引擎WEFEngine的實現(xiàn)
WEFEngine是整個WEF的核心,主要包括四部分:①WEFEngineBean,負責整個WEF框架核心功能的調(diào)度和指揮;②Processor,一個實現(xiàn)了SessionBean接口的抽象類,供開發(fā)人員繼承并實現(xiàn)其抽象方法以提供業(yè)務邏輯功能;③ProcessorLocator,實現(xiàn)了ServiceLocator模式的輔助模塊,封裝了JNDI操作的細節(jié),提供Processor的定位和創(chuàng)建;④InputManager和OutputManager,根據(jù)配置文件使用前置和后置處理器加工請求和回應。
WEFEngineBean是一個SessionBean,只有一個公有方法Process,參數(shù)是IRequest,返回值是IResponse,可能拋出BusinessException異常。代理層的代理收到從表示層發(fā)送過來的處理請求并構(gòu)造好IRequest對象后,就通過ProcessorLocator得到WEFEngineBean的實例并調(diào)用其Process方法處理IRequest對象。
在WEFEngineBean的Process方法中,首先WEFEngineBean會向SessionManager請求一個新的SessionID號,以這個SessionID號和IRequest對象構(gòu)造一個WEFData對象;然后WEFEngineBean把這個WEFData對象傳給InputManager,InputManager使用自己維護的InputDecorators處理WEFData中的IRequest對象,并把WEFData返回給WEFEngineBean。WEFEngineBean把處理之后的IRequest對象的完全限定名傳遞給ProcessorLocator,ProcessorLocator會返回給它一個可以處理這個請求的Processor的實例引用,于是這個WEFData就傳給這個Processor處理。處理完畢交還WEFData后,WEFEnginenBean再把這個對象傳給OutputManager,OutputManager再使用自己維護的OutputDecorators處理WEFData中的IResponse對象,然后把WEFData返還給WEFEngineBean。最后,WEFEngineBean向SessionManager注銷這個Session的使用,把IResponse對象返還給客戶端。如果在處理的過程中產(chǎn)生了什么異常,這個異常會隨IRepsonse對象一起返回給客戶端。
Processor是用戶使用WEF的核心擴展點,也是WEF提供給用戶使用價值的地方。這里Processor取代了用戶使用EJB的常規(guī)方法,Processor本身是一個實現(xiàn)了SessionBean接口的抽象類,它提供了一個叫做Process的抽象方法供用戶繼承擴展,Process的輸入?yún)?shù)是包裝了用戶的Request的WEFData,返回參數(shù)會是一個包裝了系統(tǒng)處理過的Response的WEFData。用戶應該繼承Processor類并實現(xiàn)其抽象方法,把自己的業(yè)務邏輯放在Process方法中實現(xiàn)。在實際使用中,Processor類應該作為一個SessionFacade模式的具體應用,以通過調(diào)用用戶編寫的其他EJB組件來實現(xiàn)業(yè)務邏輯,Processor居中調(diào)度,處理中間結(jié)果以及構(gòu)造返回值對象。這樣由于對其他EJB的調(diào)用是從服務器而不是客戶端發(fā)出的,網(wǎng)絡上的延時會小很多,其性能要比從客戶端調(diào)用有較大的提高。而且如果規(guī)劃好EJB的部署,還可以使用LocalEJB對象避免網(wǎng)絡序列化操作,這樣EJB的性能會進一步提高。而這一切對于客戶端調(diào)用是透明的,客戶端不需要作任何改變就可以享受到性能的提升,這也WEF的一個優(yōu)點。
InputManager和OutputManager具有相似的結(jié)構(gòu),它們會根據(jù)配置文件為每個用戶可能發(fā)出的請求類型構(gòu)造一個修飾器隊列。當WEFEngineBean把控制權(quán)交給它們時,它們根據(jù)請求類型依次調(diào)用修飾器隊列中的修飾器處理請求或回應。在實際應用中,可以把快速易變的業(yè)務邏輯放在前置或后置處理器中實現(xiàn),而把相對穩(wěn)定的業(yè)務邏輯流程放在ProcessorBean中,這樣通過熱替換可以實現(xiàn)業(yè)務邏輯的快速切換和升級。
4WEF在圖書管理系統(tǒng)中的應用
我們以一個基于Web的圖書管理系統(tǒng)的開發(fā)過程為例,對WEF的應用過程進行描述。基于Web的圖書管理系統(tǒng)提供通用的圖書管理功能,采用FDD(FeatureDrivenDevelopment)模式,使用Struts作為Web表示層的框架,將業(yè)務邏輯封裝在EJB中,以適應將來可能出現(xiàn)的系統(tǒng)負載不斷擴大的需要。表1是帶有開發(fā)計劃的特征表的部分內(nèi)容。
表1圖書管理系統(tǒng)特征表片斷
基于Web的圖書館管理系統(tǒng)的業(yè)務邏輯層使用EJB實現(xiàn),表示層使用Struts。如果不使用WEF,借書動作的表示層代碼片斷如下:
publicActionForwardperform(ActionMappingmapping,ActionFormform,HttpServletRequestrequest,HttpServletResponseresponse)
throwsIOException,ServletException{
//準備好借書的書號bookid和用戶標志userid
//調(diào)用EJB完成借書動作
try{
Contextctx=newInitialContext();
Objectobj=ctx.lookup(\"BorrowBookHome\");
BorrowBookHomehome=(BorrowBookHome)javax.rmi.Portable-RemoteObject.narrow(obj,BorrowBookHome.class);
BorrowBookBeanborrowBean=home.create();
borrowBean.borrow(bookid,userid);
borrowBean.remove();
}catch(BorrowFailExceptione){
//切換到處理或顯示借書錯誤的頁面
}catch(RemoteExceptione){
//切換到處理或顯示遠程連接錯誤的頁面
}catch(Exceptione){
//處理異常并切換到其他頁面
}
}
而如果借書的業(yè)務邏輯使用WEF的ProcessorBean來實現(xiàn),在WEF的Struts擴展中代碼片斷如下:
publicActionForwardprocess(ActionMappingmapping,ActionFormform,HttpServletRequestrequest,HttpServletResponseresponse)
throwsIOException,ServletException,WEFException{
//準備好借書的書號bookid和用戶標志userid
//通過WEF框架調(diào)用EJB方法
BorrowBookRequestbr=newBorrowBookRequest();
br.setBookID(bookid);
br.setUserID(userid);
BorrowBookResponseresponse=(BorrowBookResponse)sendRequest(br);
//判斷Response返回值決定以后的事件流向
}
可以看到,在WEFAction中的代碼非常地簡潔明了,就是構(gòu)造一個請求對象、發(fā)送請求、得到返回對象。它不需要任何異常處理代碼,因為常見異常已經(jīng)被父類處理,特殊異常會由異常處理模塊處理,只需要在配置文件中聲明遇到這樣的異常應該重定位到哪個頁面,顯示哪些信息就行了。
5結(jié)束語
為了提高EJB調(diào)用的靈活性和效率,本文提出了一個基于Struts的軟件開發(fā)框架WEF。通過圖書館管理系統(tǒng)的開發(fā)過程的分析可以看出,通過WEF的包裝,EJB組件的調(diào)用將變得更加簡潔,這有助于提高軟件系統(tǒng)的開發(fā)效率,減小維護代價。同時,除了代碼編寫上的便利之外,使用WEF還有如下好處:
(1)Action中完全不管使用什么樣的方式訪問服務端,這樣更改傳輸協(xié)議或更改服務器地址時不需要修改Action類的代碼;
(2)服務端編程很靈活,通過配置合適的輸入前置處理器和輸出后置處理器可以快速地響應用戶需求的變化,一切只需要修改配置文件,刷新配置管理器;
(3)表示層和業(yè)務邏輯層可以分開測試,便于安排進度。
參考文獻:
[1]AltendorfE,HohmanM,ZabickiR.UsingJ2EEonaLarge,WebbasedProject[J].IEEESoftware,2002,19:8189.[2]LunneyT,McCaugheyA.ComponentbasedDistributedSystems:CORBAandEJBinContext[J].ComputerPhysicsCommunications,2000,127:207214.
[3]ManuelP,AlGhamdiJ.ADatacentricDesignforntierArchitecture[J].InformationSciences,2003,150:195206.
[4]McArthurK,SaiedianH,ZandM.AnEvaluationoftheImpactofComponentbasedArchitecturesonSoftwareReusability[J].InformationandSoftwareTechnology,2002,44:351359.
[5]AniorteP.ADistributedAdaptableSoftwareArchitectureDerivedfromaComponentModel[J].ComputerStandardsandInterfaces,2003,25:275282.
[6]SousaJ,GarlanD.FormalModelingoftheEnterpriseJavaBeansTMComponentIntegrationFramework[J].InformationandSoftwareTechnology,2001,43:171188.
[7]葛聲,馬殿富,等.基于Web服務的網(wǎng)絡軟件運行平臺研究與實現(xiàn)[J].北京航空航天大學學報,2003,29(10):897900.
作者簡介:
徐博藝(1966),男,山東人,副教授,主要研究方向為信息管理與信息系統(tǒng)、商務智能、電子商務;
姜麗紅(1968),女,山東人,副教授,主要研究方向為信息系統(tǒng)應用;
董理(1982),男,碩士,主要研究方向為信息系統(tǒng)應用。