===================================
提綱:
===================================
一、概述
二、無
狀態(tài)會(huì)話Bean
三、有狀態(tài)會(huì)話Bean
四、客戶端
接口 4.1 Remote接口
4.2 Home接口
五、實(shí)例
5.1 有狀態(tài)會(huì)話Bean
5.2 Home接口
5.3 Remote接口
5.4 安排描寫器
5.5 客戶
程序 5.6 運(yùn)行
===================================
正文:
===================================
一、概述 在企業(yè)級(jí)利用系統(tǒng)內(nèi),會(huì)話Bean是一種代表客戶程序履行把持的EJB。對(duì)于EJB客戶程序來說,會(huì)話Bean經(jīng)常起著進(jìn)口點(diǎn)或“前線”EJB的作用。EJB客戶程序通過與會(huì)話Bean的交互,從企業(yè)利用系統(tǒng)獲取它們想要利用的功效或服務(wù)。
正如其名字所示,會(huì)話Bean類似于一個(gè)交互式的會(huì)話。會(huì)話Bean是不共享的,正如交互式會(huì)話只能有一個(gè)用戶,而且會(huì)話Bean也不具備持久化的特點(diǎn)(即它的數(shù)據(jù)不保存到數(shù)據(jù)庫(kù))。一旦客戶程序結(jié)束運(yùn)行,會(huì)話Bean也就不再關(guān)聯(lián)到客戶程序。
會(huì)話Bean有兩種類型:有狀態(tài)會(huì)話Bean(Stateful Session Bean),無狀態(tài)會(huì)話Bean(Stateless Session Bean)。
有狀態(tài)會(huì)話Bean
對(duì)象的狀態(tài)由實(shí)例變量的值描寫。對(duì)于有狀態(tài)會(huì)話Bean,實(shí)例變量描寫了客戶程序與Bean的會(huì)話的狀態(tài)。鑒于客戶程序與Bean的交互關(guān)系,Bean的狀態(tài)信息通常稱為會(huì)話狀態(tài)。
在客戶程序與Bean交互期間,狀態(tài)信息一直有效。假如客戶程序運(yùn)行結(jié)束或拆除了Bean,則會(huì)話結(jié)束,狀態(tài)信息也不再保存。然而,狀態(tài)信息的這種臨時(shí)性并不成為標(biāo)題,由于當(dāng)客戶程序與Bean之間的會(huì)話終止,狀態(tài)信息也就沒有必要再保存了。
無狀態(tài)會(huì)話Bean
無狀態(tài)會(huì)話Bean不為特定的客戶程序保存會(huì)話狀態(tài)??蛻舫绦蛘{(diào)用無狀態(tài)Bean的
方法時(shí),Bean的實(shí)例變量可以包含狀態(tài)信息,但狀態(tài)信息僅在該次調(diào)用期間有效。當(dāng)方法調(diào)用結(jié)束,狀態(tài)信息也就不再保存。除了Bean方法正在履行的時(shí)間之外,所有無狀態(tài)Bean的實(shí)例都是等價(jià)的,這使得EJB容器能夠把Bean的實(shí)例分配給任意客戶程序。
由于無狀態(tài)會(huì)話Bean支撐多個(gè)客戶程序,對(duì)于那些客戶程序數(shù)目很大的利用,無狀態(tài)會(huì)話Bean具有更好的可伸縮性。一般地,對(duì)于支撐同樣數(shù)目標(biāo)客戶程序來說,利用需要的無狀態(tài)會(huì)話Bean數(shù)目少于有狀態(tài)會(huì)話Bean數(shù)目。
一些時(shí)候,EJB容器可能把有狀態(tài)會(huì)話Bean保存到第二級(jí)存儲(chǔ)設(shè)備,但容器永遠(yuǎn)不會(huì)保存無狀態(tài)會(huì)話Bean。因此,無狀態(tài)會(huì)話Bean比有狀態(tài)會(huì)話Bean有著更好的性能。
一般地,在下列情況下,我們可以應(yīng)用會(huì)話Bean:
在任意時(shí)刻只有一個(gè)客戶程序訪問Bean的實(shí)例。
Bean的狀態(tài)無需持久化,只在短期內(nèi)生存(比如幾個(gè)小時(shí))。
假如滿足任意以下條件,應(yīng)用有狀態(tài)會(huì)話Bean比較合適:
Bean的狀態(tài)描寫了Bean與特定客戶程序的交互。
Bean需要保存有關(guān)客戶程序的信息,且保存期限必須跨越多次方法調(diào)用。
Bean擔(dān)負(fù)著客戶程序到利用其他組件之間的中間人的角色,為客戶程序供給一個(gè)簡(jiǎn)化的服務(wù)視圖。
Bean治理著多個(gè)EJB的工作流程。
為進(jìn)步性能,當(dāng)Bean具有任意下面的特點(diǎn)之一時(shí),最好選用無狀態(tài)會(huì)話Bean:
Bean的狀態(tài)信息不包含任何針對(duì)特定客戶程序的數(shù)據(jù)。
Bean從數(shù)據(jù)庫(kù)提取一組客戶程序經(jīng)常應(yīng)用的只讀數(shù)據(jù)。例如,Bean從數(shù)據(jù)庫(kù)提取出本月銷售的產(chǎn)品信息。
二、無狀態(tài)會(huì)話Bean 無狀態(tài)會(huì)話Bean不在EJB之內(nèi)保存面向特定客戶程序的狀態(tài)信息,但這并不意味著這類EJB不在本身的域或關(guān)聯(lián)的對(duì)象里面保存任何狀態(tài)數(shù)據(jù),其真實(shí)含義是,這類Bean保持的狀態(tài)信息不是為特定EJB客戶程序下一次訪問或應(yīng)用而保存。
這種特點(diǎn)使得EJB容器能夠更高效、更機(jī)動(dòng)地治理無狀態(tài)會(huì)話Bean。在任意時(shí)刻,任意一個(gè)客戶程序可以應(yīng)用容器創(chuàng)立的任意一個(gè)無狀態(tài)會(huì)話Bean的實(shí)例。因此,容器可認(rèn)為這類實(shí)例結(jié)構(gòu)一個(gè)緩沖池,根據(jù)客戶程序的需求從緩沖池分配Bean的實(shí)例,無需顧慮哪一個(gè)實(shí)例屬于哪一個(gè)客戶程序。此外,必要時(shí)容器能夠方便地創(chuàng)立或拆除Bean的實(shí)例,根據(jù)利用規(guī)模和資源情況作出調(diào)劑。固然無狀態(tài)會(huì)話Bean可能擁有狀態(tài)信息,但在兩次對(duì)Bean實(shí)例的持續(xù)調(diào)用之間,開發(fā)者不能假定這些狀態(tài)信息的正當(dāng)性。
圖一顯示了無狀態(tài)會(huì)話Bean組件結(jié)構(gòu)的基礎(chǔ)系統(tǒng)結(jié)構(gòu)。
位于圖一頂真?zhèn)€是javax.ejb.EnterpriseBean接口,它是所有EJB的基礎(chǔ)接口。從EnterpriseBean接口派生出了javax.ejb.SessionBean接口。公用的、非終極的、非抽象的無狀態(tài)會(huì)話EJB,比如圖一顯示的MyStatelessSessionEJBean,必須實(shí)現(xiàn)javax.ejb.SessionBean接口。無狀態(tài)會(huì)話EJB實(shí)現(xiàn)公用的、非終極的、非抽象的業(yè)務(wù)方法,比如圖一顯示的someMethod()和anotherMethod()。實(shí)現(xiàn)會(huì)話Bean的類必須有一個(gè)公用的、不帶參數(shù)的結(jié)構(gòu)函數(shù),且不應(yīng)當(dāng)實(shí)現(xiàn)finalize()方法。
無狀態(tài)會(huì)話Bean上定義的setSessionContext()方法用來把一個(gè)SessionContext的實(shí)例傳進(jìn)EJB,它也是SessionBean接口上定義的第一個(gè)由容器調(diào)用的方法。SessionContext對(duì)象封裝了一個(gè)EJB會(huì)話容器高低文的接口,支撐會(huì)話Bean的實(shí)例訪問容器供給的運(yùn)行時(shí)會(huì)話高低文。在Bean實(shí)例生存期間,會(huì)話高低文將一直保持與Bean實(shí)例的關(guān)聯(lián)。
對(duì)于無狀態(tài)會(huì)話Bean,盡管在SessionBean接口中沒有定義ejbCreate()方法,但它是一個(gè)要害的把持。無狀態(tài)會(huì)話Bean必須定義一個(gè)返回值為void的ejbCreate()方法,容器準(zhǔn)備創(chuàng)立Bean的實(shí)例時(shí)將調(diào)用這個(gè)方法。容器決定創(chuàng)立Bean的實(shí)例可能是由于它要結(jié)構(gòu)一個(gè)Bean實(shí)例的緩沖池,也有可能是由于它吸收到了客戶程序的懇求。因此,ejbCreate()方法屬于一種由EJB實(shí)現(xiàn)的特別的結(jié)構(gòu)函數(shù)或初始化方法。
當(dāng)容器決定不讓Bean的實(shí)例持續(xù)處理客戶程序的懇求時(shí),它就會(huì)調(diào)用Bean實(shí)例的ejbRemove()方法。對(duì)于無狀態(tài)會(huì)話Bean,何時(shí)調(diào)用Bean實(shí)例的ejbRemove()方法由容器單獨(dú)決定,不受EJB客戶程序的任何影響。
三、有狀態(tài)會(huì)話Bean
有狀態(tài)會(huì)話Bean在EJB之內(nèi)保存的狀態(tài)信息與EJB客戶程序有著明確的關(guān)系。有狀態(tài)會(huì)話Bean的狀態(tài)信息是指保存在Bean實(shí)例的域里面的數(shù)據(jù),以及Bean實(shí)例持有的各種對(duì)象里面的數(shù)據(jù)。當(dāng)一個(gè)EJB客戶程序在某一時(shí)刻訪問一個(gè)有狀態(tài)會(huì)話Bean,且轉(zhuǎn)變了該Bean實(shí)例的狀態(tài),則狀態(tài)信息將被保存,下一次Bean再次被訪問時(shí),Bean的實(shí)例將應(yīng)用本來保存的狀態(tài)信息。
對(duì) 于有狀態(tài)會(huì)話Bean,容器承擔(dān)著更多的Bean治理方面的責(zé)任。實(shí)際上,客戶程序創(chuàng)立或拆除有狀態(tài)會(huì)話Bean直接關(guān)系到服務(wù)器端Bean實(shí)例的創(chuàng)立和拆除。此外,當(dāng)資源緊張時(shí),容器可能決定把一個(gè)或者多個(gè)有狀態(tài)會(huì)話Bean串行化(也就是鈍化)到持久性存儲(chǔ)設(shè)備,一旦資源重新空閑,或涌現(xiàn)了客戶程序的懇求,被鈍化的Bean必須激活并轉(zhuǎn)進(jìn)運(yùn)動(dòng)內(nèi)存。因此,設(shè)計(jì)有狀態(tài)會(huì)話Bean時(shí),開發(fā)者必須考慮更多的標(biāo)題。
圖二顯示了有狀態(tài)會(huì)話Bean組件結(jié)構(gòu)的基礎(chǔ)系統(tǒng)結(jié)構(gòu)。
公用的、非終極的、非抽象的有狀態(tài)會(huì)話Bean,如圖二顯示的MyStatefulSessionEJBean,必須實(shí)現(xiàn)SessionBean接口。SessionBean接口從EnterpriseBean接口派生。另外,有狀態(tài)會(huì)話EJB也實(shí)現(xiàn)公用的、非終極的、非抽象的業(yè)務(wù)方法,比如圖二顯示的someMethod()方法和anotherMethod()方法。實(shí)現(xiàn)會(huì)話Bean的類必須有一個(gè)公用的、不帶參數(shù)的結(jié)構(gòu)方法,且不應(yīng)實(shí)現(xiàn)finalize()方法。最后,有狀態(tài)會(huì)話Bean可以實(shí)現(xiàn)javax.ejb.SessionSynchronization接口,使得Bean能夠收到某些事務(wù)治理方面的事件通知,但這是可選的。
由于狀態(tài)信息對(duì)于有狀態(tài)會(huì)話Bean的重要性,創(chuàng)立Bean時(shí)初始化把持也很重要。有狀態(tài)會(huì)話Bean可以定義一個(gè)或者多個(gè)ejbCreate(...)方法,這些方法帶有零個(gè)或者多個(gè)輸進(jìn)參數(shù),方法的返回值類型是void。傳遞給這類方法的具體參數(shù)由利用本身決定,但方法的名字必須是ejbCreate()。與無狀態(tài)會(huì)話Bean上的ejbCreate()調(diào)用不同,有狀態(tài)會(huì)話Bean的ejbCreate()方法綁定到EJB客戶程序,EJB客戶程序?qū)⒁恢睉?yīng)用特定的EJB實(shí)例。另外也請(qǐng)留心,正如對(duì)于無狀態(tài)會(huì)話Bean,在調(diào)用任何ejbCreate()方法之前,容器將調(diào)用有狀態(tài)會(huì)話Bean的setSessionContext()方法。
假如有狀態(tài)會(huì)話Bean的ejbRemove()方法被調(diào)用,則表明對(duì)應(yīng)的客戶程序已經(jīng)決定不讓該Bean持續(xù)處理懇求。另外,會(huì)話最大超時(shí)時(shí)間達(dá)到時(shí),容器也會(huì)調(diào)用Bean的ejbRemove()方法。
設(shè)計(jì)有狀態(tài)會(huì)話Bean的過程中,有時(shí)最重要的事情就是Bean的鈍化和激活把持。正如前面所指出的,容器鈍化某個(gè)Bean時(shí),它將串行化Bean的內(nèi)容,并把這些信息寫進(jìn)某個(gè)持久性存儲(chǔ)設(shè)備。容器之所以鈍化Bean是由于內(nèi)存資源不足。通常,容器通過某種情勢(shì)的“最近最少應(yīng)用”算法斷定應(yīng)當(dāng)鈍化哪些Bean的實(shí)例(當(dāng)然,實(shí)際所用的算法由具體的平臺(tái)決定)。
在鈍化Bean的實(shí)例之前,容器會(huì)調(diào)用Bean的ejbPassivate()方法,有狀態(tài)會(huì)話Bean必須實(shí)現(xiàn)這個(gè)方法。在ejbPassivate()方法中,我們應(yīng)當(dāng)掃除所有不能串行化和持久化的資源,比如數(shù)據(jù)庫(kù)連接和打開的文件句柄。ejbPassivate()方法履行完畢之后,所有仍未封閉的對(duì)象應(yīng)當(dāng)能夠被容器鈍化。
假如涌現(xiàn)了對(duì)已經(jīng)被鈍化的Bean的懇求,或者有了空閑的資源,容器將激活被鈍化的Bean。此時(shí),容器讀取以前被串行化的Bean狀態(tài)數(shù)據(jù),并在運(yùn)動(dòng)內(nèi)存中用該狀態(tài)數(shù)據(jù)重新結(jié)構(gòu)Bean。一旦完成對(duì)Bean狀態(tài)的重新結(jié)構(gòu),容器將調(diào)用有狀態(tài)會(huì)話Bean的ejbActivate()方法。在ejbActivate()方法中,我們應(yīng)當(dāng)重新結(jié)構(gòu)出那些在ejbPassivate()方法內(nèi)封閉的資源。另一方面,假如Bean保存在持久性存儲(chǔ)設(shè)備中超過了必定的時(shí)間(一個(gè)可配置的限制時(shí)間),運(yùn)行平臺(tái)可能會(huì)從持久化存儲(chǔ)中刪除本來保存的Bean。
四、客戶端接口 前面我們懂得了如何結(jié)構(gòu)服務(wù)器真?zhèn)€會(huì)話Bean組件,接下來看看客戶程序如何利用這些組件供給的服務(wù)。客戶程序與會(huì)話Bean的交互重要通過兩種接口完成:會(huì)話Bean的Home接口,會(huì)話Bean的Remote接口。會(huì)話Bean的Home接口重要作為一個(gè)創(chuàng)立會(huì)話Bean對(duì)象引用的工廠應(yīng)用,與此相對(duì)應(yīng),會(huì)話Bean的Remote接口供給了散布式會(huì)話Bean對(duì)象的利用層把持的客戶端接口。
4.1 Remote接口 會(huì)話Bean的Remote接口定義了一組利用層的、可在特定會(huì)話Bean上調(diào)用的、散布式的把持。遠(yuǎn)程接口描寫了客戶程序所看到的EJB,正如RMI遠(yuǎn)程接口描寫了客戶程序所看到的RMI服務(wù)器。
圖三描寫了結(jié)構(gòu)和應(yīng)用散布式會(huì)話EJB Remote客戶端接口的基礎(chǔ)邏輯結(jié)構(gòu)。
所有指向散布式EJB對(duì)象的遠(yuǎn)程利用層接口,比如圖三顯示的MySessionEJB,必須從javax.ejb.EJBObject接口派生,而EJBObject接口又從java.rmi.Remote接口派生,java.rmi.Remote接口為遠(yuǎn)程EJB接口增長(zhǎng)了散布式RMI支撐。從實(shí)現(xiàn)原理來看,遠(yuǎn)程接口在客戶端應(yīng)用了容器供給的Stub程序,Stub程序把調(diào)用傳遞到服務(wù)器端骨架程序(Skeleton),骨架程序再把調(diào)用委托給實(shí)際的服務(wù)器端EJB組件,比如圖三顯示的MySessionEJBean。EJB容器對(duì)于哪一個(gè)Bean實(shí)例被選用以及調(diào)用如何在服務(wù)器端傳遞負(fù)有終極責(zé)任,但成果總是一樣的,即客戶程序?qū)JB遠(yuǎn)程接口中的方法的調(diào)用,終極導(dǎo)致對(duì)應(yīng)的服務(wù)器端EJB組件實(shí)例上的方法調(diào)用。
每一個(gè)會(huì)話EJB組件必須有一個(gè)遠(yuǎn)程EJB接口。對(duì)于EJB服務(wù)器端組件上的每一個(gè)利用層方法,比如MySessionEJBean.someMethod(),EJB客戶端遠(yuǎn)程接口上必須定義一個(gè)對(duì)應(yīng)的方法,例如MySessionEJB.someMethod()。由于散布式特征的請(qǐng)求,利用層遠(yuǎn)程接口中的每一個(gè)方法必須聲明它可以拋出java.rmi.RemoteException異常。在遠(yuǎn)程EJB對(duì)象上,除了利用層方法之外,還有一組持續(xù)自EJBObject接口的方法可供調(diào)用。
4.2 Home接口 會(huì)話Bean的客戶程序利用Home接口創(chuàng)立會(huì)話Bean的引用以及拆除這些引用。當(dāng)然,這些引用都通過遠(yuǎn)程會(huì)話Bean接口對(duì)象實(shí)現(xiàn)。客戶程序應(yīng)當(dāng)總是通過Home接口創(chuàng)立EJB的引用,由于這種方法使得容器有必不可少的機(jī)會(huì)處理EJB實(shí)例資源分配方面的工作。反之,假如客戶程序繞過了Home接口,直接應(yīng)用通過其他手段獲得的EJBObject對(duì)象句柄,比如通過JNDI查找,則可能導(dǎo)致線程方面的標(biāo)題,由于不能有一個(gè)以上的客戶程序線程應(yīng)用同一個(gè)服務(wù)器端Bean實(shí)例。
圖四顯示了結(jié)構(gòu)會(huì)話Bean Home接口的基礎(chǔ)系統(tǒng)結(jié)構(gòu),以及客戶程序如何利用這些接口。我們利用JNDI獲取EJB Home接口對(duì)象的句柄,比如圖四顯示的MySessionEJBHome。MySessionEJBHome接口從標(biāo)準(zhǔn)的javax.ejb.EJBHome接口派生。EJB Home接口對(duì)象也在客戶端由Stub程序?qū)崿F(xiàn),Stub程序與服務(wù)器真?zhèn)€Skeleton程序、容器通信,容器創(chuàng)立或拆除會(huì)話Bean的實(shí)例,并把調(diào)用傳遞給會(huì)話Bean的實(shí)例。
EJB客戶程序創(chuàng)立一個(gè)新的EJB引用時(shí),它首先要獲得一個(gè)EJB Home接口句柄。這個(gè)任務(wù)通過JNDI完成。在J2EE環(huán)境下,客戶程序能夠應(yīng)用InitialContext對(duì)象的默認(rèn)無參數(shù)結(jié)構(gòu)函數(shù),并通過InitialContext.lookup()調(diào)用方便地查找EJB Home接口的句柄。傳遞給InitialContext.lookup()的名字可以引用一個(gè)元素,該元素在客戶程序的XML格式的安排描寫器中定義。元素定義的內(nèi)容包含引用名稱、被引用EJB的類型、Home接口信息、Remote接口信息等,如下面的例子所示:
MyStatefulFundManager
Session
StatefulFundManagerHome
StatefulFundManager
StatefulFundManagerBean
Home接口定義了一個(gè)或者多個(gè)create()方法,這些方法代表著創(chuàng)立EJB對(duì)象的各種方法。對(duì)于EJB類里面定義的每一個(gè)ejbCreate(...)方法,Home接口上必須定義一個(gè)對(duì)應(yīng)的create(...)方法。create(...)方法可以包含零個(gè)或者多個(gè)輸進(jìn)參數(shù),與對(duì)應(yīng)的ejbCreate(...)方法需要的初始化參數(shù)類型有關(guān),但這些create(...)方法都返回一個(gè)EJB遠(yuǎn)程接口的實(shí)例(例如MySessionEJB)。create(...)方法還必須能夠拋出java.rmi.RemoteException異常和javax.ejb.CreateException異常,能夠拋出各種為對(duì)應(yīng)的ejbCreate(...)方法定義的利用層異常。
由于無狀態(tài)會(huì)話Bean只定義一個(gè)不帶參數(shù)的ejbCreate()方法,無狀態(tài)會(huì)話Bean的Home接口也只能定義一個(gè)不帶參數(shù)的create()方法。在無狀態(tài)會(huì)話Bean上調(diào)用create()方法只導(dǎo)致容器從緩沖池取出一個(gè)Bean的實(shí)例,不必定導(dǎo)致容器立即調(diào)用Bean的ejbCreate()方法。但是,對(duì)于有狀態(tài)會(huì)話Bean,容器將調(diào)用Bean實(shí)例的ejbCreate(...)方法,并在調(diào)用時(shí)供給所有傳進(jìn)Home接口create(...)方法的參數(shù)。
五、實(shí)例 這里我們要分析的是一個(gè)有狀態(tài)會(huì)話Bean利用的例子。這是一個(gè)很簡(jiǎn)略的資金治理程序,包含一個(gè)名為StatefulFundManagerEJB的有狀態(tài)會(huì)話EJB。利用支撐資金存進(jìn)和提取把持,但數(shù)據(jù)僅在會(huì)話期間有效,即不能持久保存。利用包含如下文件:
會(huì)話Bean類:StatefulFundManagerEJB.java
Home接口:StatefulFundManagerHome.java
遠(yuǎn)程接口:StatefulFundManager.java
此外,本例還包含一個(gè)InsufficientBalanceException.java文件定義的異常。完整的源代碼和利用EAR文件可以從本文后面下載。
5.1 有狀態(tài)會(huì)話Bean
本例的會(huì)話Bean名為StatefulFundManagerEJB。和所有其他會(huì)話Bean一樣,StatefulFundManagerEJB滿足以下請(qǐng)求:
實(shí)現(xiàn)SessionBean接口。
類定義成public。
類不能定義成abstract或final。
實(shí)現(xiàn)一個(gè)或者多個(gè)ejbCreate()方法。
實(shí)現(xiàn)業(yè)務(wù)方法。
包含一個(gè)公用的、不帶參數(shù)的結(jié)構(gòu)函數(shù)。
不能定義finalize()方法。
SessionBean接口定義了ejbRemove()、ejbActivate()、ejbPassivate()和setSessionContext()方法。StatefulFundManagerEJB不需要用到這些方法,但由于SessionBean接口聲明了它們,因此必須實(shí)現(xiàn)它們。在StatefulFundManagerEJB中,這些方法都是空的。
5.1.1 ejbCreate()方法 EJB在容器之內(nèi)運(yùn)行,客戶程序不能直接創(chuàng)立Bean的實(shí)例,只有容器才干創(chuàng)立EJB的實(shí)例。創(chuàng)立EJB實(shí)例時(shí),利用的把持步驟如下:
客戶程序調(diào)用Home對(duì)象上的create()方法:
StatefulFundManager manager = home.create(2000);
容器結(jié)構(gòu)EJB的實(shí)例。 容器調(diào)用StatefulFundManager上合適的ejbCreate()方法。下面是本例ejbCreate()方法的實(shí)現(xiàn)代碼:
public void ejbCreate(double amount) throws CreateException {
if (amount < 0) {
throw new CreateException("資金數(shù)目毛病");
}else {
this.amount = amount;
}
}
ejbCreate()方法初始化Bean的狀態(tài)。例如,上面的ejbCreate()方法用參數(shù)傳進(jìn)的數(shù)值初始化資金數(shù)目(amount)。當(dāng)輸進(jìn)參數(shù)非法時(shí),ejbCreate()方法通常拋出CreateException異常。ejbCreate()方法應(yīng)當(dāng)滿足如下請(qǐng)求:
訪問把持潤(rùn)飾符必須是public。
返回void。
如Bean支撐遠(yuǎn)程訪問,參數(shù)類型必須是正當(dāng)?shù)腞MI類型。
不能帶有static或final潤(rùn)飾符。
5.1.2 業(yè)務(wù)方法 會(huì)話Bean的根本目標(biāo)是為客戶程序供給業(yè)務(wù)方法,客戶程序通過create()方法返回的遠(yuǎn)程對(duì)象引用調(diào)用業(yè)務(wù)方法。從客戶端看來,業(yè)務(wù)方法似乎在本地履行,但實(shí)際上業(yè)務(wù)方法在遠(yuǎn)程的會(huì)話Bean上履行。下面的代碼片斷顯示了StatefulFundManagerTestClient客戶程序如何調(diào)用業(yè)務(wù)方法:
if (e.getSource() == addFunds) {
// 調(diào)用治理器EJB上的addFunds方法
manager.addFunds(Double.parseDouble(amount.getText()));
// 設(shè)置新的余額
String currencyOut = currencyFormatter.format(manager.getBalance());
status.setText(msg + currencyOut);
}
if (e.getSource() == withdrawFunds) {
// 調(diào)用治理器EJB上的withdrawFunds方法
manager.withdrawFunds(Double.parseDouble(amount.getText()));
// 設(shè)置新的余額
String currencyOut = currencyFormatter.format(manager.getBalance());
status.setText(msg + currencyOut);
}
下面是StatefulFundManagerEJB實(shí)現(xiàn)的其中兩個(gè)業(yè)務(wù)方法:
public void addFunds(double amount) {
if (amount <= 0){
return;
}
this.amount += amount;
}
public void withdrawFunds(double amount) throws
InsufficientBalanceException {
if (this.amount < amount) {
throw (new InsufficientBalanceException());
}
this.amount -= amount;
}
聲明業(yè)務(wù)方法時(shí)應(yīng)屈服以下規(guī)矩:
方法名字不能與EJB系統(tǒng)定義的標(biāo)準(zhǔn)方法沖突,例如,方法名字不能是ejbCreate()或ejbActivate()。
訪問把持潤(rùn)飾符必須是pubic。
假如Bean答應(yīng)遠(yuǎn)程訪問,則參數(shù)和返回值必須是正當(dāng)?shù)腞MI類型。
不能有static或final潤(rùn)飾符。
5.2 Home接口 對(duì)于會(huì)話Bean來說,Home接口的目標(biāo)是定義供客戶程序調(diào)用的create()方法。Home接口中的每一個(gè)create()方法對(duì)應(yīng)著Bean類中的一個(gè)ejbCreate()方法。前面我們已經(jīng)看到了Bean類定義的ejbCreate()方法,請(qǐng)比較Home接口StatefulFundManagerHome定義的create()方法:
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
public interface StatefulFundManagerHome extends EJBHome {
StatefulFundManager create(double amount) throws RemoteException,
CreateException;
}
ejbCreate()方法和create()方法有著類似的特點(diǎn),但兩者又有重要的差別。在Home接口中定義create()方法的規(guī)矩如下:
create()方法中參數(shù)的數(shù)目和類型必須與對(duì)應(yīng)的ejbCreate()方法的參數(shù)數(shù)目和類型匹配。
create()方法的參數(shù)和返回值必須是正當(dāng)?shù)腞MI類型。
create()方法返回EJB的遠(yuǎn)程接口類型(ejbCreate()方法返回void)。
create()方法的throws子句必須包含java.rmi.RemoteException和javax.ejb.CreateException。
5.3 Remote接口 遠(yuǎn)程接口定義了供客戶程序調(diào)用的業(yè)務(wù)方法。StatefulFundManagerEJB的遠(yuǎn)程接口是StatefulFundManager,定義如下:
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
public interface StatefulFundManager extends EJBObject {
public void addFunds(double amount) throws RemoteException;
public void withdrawFunds(double amount)
throws InsufficientBalanceException, RemoteException;
public double getBalance() throws RemoteException;
}
遠(yuǎn)程接口的定義必須符合如下請(qǐng)求:
遠(yuǎn)程接口中定義的每一個(gè)方法必須與EJB類里面定義的一個(gè)方法匹配。
參數(shù)和返回值類型必須是正當(dāng)?shù)腞MI類型。
throws子句必須包含java.rmi.RemoteException。
5.4 安排描寫器 編譯好Bean的代碼后,還應(yīng)當(dāng)把Bean封裝成JAR文件。EJB模塊安排描寫器的根元素是。元素里面可以包含一個(gè)元素,元素可以包含一組元素。每一個(gè)元素描寫一個(gè)會(huì)話Bean的配置和安排信息。
下面給出了本例ejb-jar.xml文件的重要內(nèi)容。元素定義了會(huì)話Bean的元數(shù)據(jù)、EJB JAR文件內(nèi)的唯一名稱、Bean的類名稱和接口名稱、會(huì)話Bean的類型、安全信息,事務(wù)信息等。
StatefulFundManagerJAR
StatefulFundManagerBean
StatefulFundManagerBean
StatefulFundManagerHome
StatefulFundManager
StatefulFundManagerEJB
Stateful
Container
一般地,配置和安排會(huì)話Bean時(shí)還需要面向特定平臺(tái)的安排描寫器文件,這種文件通??梢杂闷脚_(tái)供給的GUI安排工具編寫,此處不再贅述,請(qǐng)參見本文下載代碼中的例子。
5.5 客戶程序 客戶程序是一個(gè)Swing程序,運(yùn)行界面如圖五所示。在文本框中輸進(jìn)數(shù)字,點(diǎn)擊“存進(jìn)資金”增長(zhǎng)資金余額,點(diǎn)擊“取出資金”減少資金余額。
5.6 運(yùn)行 在下面的闡明中,我們假定運(yùn)行平臺(tái)是SUN的J2EE SDK、Windows 2000,且利用已經(jīng)打包成StatefulFundManager.ear文件。關(guān)于如何把利用打包成EAR文件的具體闡明,請(qǐng)參見開發(fā)平臺(tái)的相干文檔。
首先履行j2ee啟動(dòng)J2EE服務(wù)器。然后,在另一個(gè)命令窗口中履行deploytool。在deploytool中,選擇菜單“File-->Open”,打開StatefulFundManager.ear文件。接著,選擇菜單“Tools --> Deploy”,安排利用。涌現(xiàn)安排提示時(shí),選中“Return Client JAR”檢查框。
安排完畢后,在一個(gè)命令窗口中進(jìn)進(jìn)StatefulFundManager.ear文件(StatefulFundManagerClient.jar文件)所在目錄,把APPCPATH環(huán)境變量設(shè)置成StatefulFundManagerClient.jar。然后,履行下面的命令啟動(dòng)客戶程序:
runclient -client StatefulFundManager.ear -name StatefulFundManagerTestClient -textauth
輸進(jìn)用戶名字j2ee,輸進(jìn)密碼j2ee,即可啟動(dòng)程序??蛻舫绦虻倪\(yùn)行界面請(qǐng)參見圖五。
下載文本的代碼:J2EESessionEJB_code.zip (
http://210.51.0.82:7001/pub/attachment/2002/3/12756.zip)