EJB 30入門(mén)經(jīng)典.ppt_第1頁(yè)
EJB 30入門(mén)經(jīng)典.ppt_第2頁(yè)
EJB 30入門(mén)經(jīng)典.ppt_第3頁(yè)
EJB 30入門(mén)經(jīng)典.ppt_第4頁(yè)
EJB 30入門(mén)經(jīng)典.ppt_第5頁(yè)
已閱讀5頁(yè),還剩231頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、EJB 3.0 入門(mén)經(jīng)典,什么是EJB,Enterprice JavaBeans 是一個(gè)用于分布式業(yè)務(wù)應(yīng)用的標(biāo)準(zhǔn)服務(wù)端組件模型。采用Enterprice JavaBeans 架構(gòu)編寫(xiě)的應(yīng)用是可伸的、事務(wù)性的、多用戶(hù)安全的??梢砸淮尉帉?xiě)這些應(yīng)用,然后部署在任何支持Enterprice JavaBeans 規(guī)范的服務(wù)器平臺(tái),如jboss、weblogic 等。,EJB的分類(lèi),Enterprise JavaBean(EJB)定義了三種企業(yè)Bean,分別是會(huì)話(huà)Bean(Session Bean),實(shí)體Bean(Entity Bean)和消息驅(qū)動(dòng)Bean(MessageDriven Bean)。 會(huì)話(huà)B

2、ean 會(huì)話(huà)Bean 用于實(shí)現(xiàn)業(yè)務(wù)邏輯,它分為有狀態(tài)bean 和無(wú)狀態(tài)bean。每當(dāng)客戶(hù)端發(fā)出EJB 調(diào)用請(qǐng)求時(shí),容器就會(huì)選擇一個(gè)Session Bean 來(lái)為客戶(hù)端服務(wù)。會(huì)話(huà)Bean 可以直接訪問(wèn)數(shù)據(jù)庫(kù),但更多時(shí)候,它是通過(guò)實(shí)體Bean 實(shí)現(xiàn)數(shù)據(jù)訪問(wèn)。 實(shí)體Bean: 從名字上我們就能猜到,實(shí)體bean 代表真實(shí)物體的數(shù)據(jù)。在EJB3.0 中,實(shí)體bean 僅作為普通Java 對(duì)象來(lái)使用,它負(fù)責(zé)跟數(shù)據(jù)庫(kù)表進(jìn)行對(duì)象與關(guān)系映射(O/R Mapping)。 消息驅(qū)動(dòng)Bean(MDB): MDB 是設(shè)計(jì)用來(lái)專(zhuān)門(mén)處理基于消息請(qǐng)求的組件。它能夠收發(fā)異步JMS 消息,并能夠輕易地與其他EJB 交互。它特別

3、適合用于當(dāng)一個(gè)業(yè)務(wù)執(zhí)行的時(shí)間很長(zhǎng),而執(zhí)行結(jié)果無(wú)需實(shí)時(shí)向用戶(hù)反饋的這樣一個(gè)場(chǎng)合。,EJB 的運(yùn)行環(huán)境,EJB 需要運(yùn)行在EJB 容器,每個(gè)JavaEE 應(yīng)用服務(wù)器都含有EJB 容器和Web 容器,所以既可以運(yùn)行EJB,也可以運(yùn)行Web 應(yīng)用。目前支持EJB3.0 的應(yīng)用服務(wù)器有Jboss(4.2.x 以上版本)、Glassfish、Weblogic(10 以上版本)、Sun Application Server(9.0 以上版本)、Oracle Application Server(10g 以上版本)和我們國(guó)內(nèi)的apusic 應(yīng)用服務(wù)器。本書(shū)將介紹Jboss 和Weblogic,前者是使用者最多

4、的開(kāi)源應(yīng)用服務(wù)器,后者是市場(chǎng)占有率最高的商業(yè)應(yīng)用服務(wù)器。 注意:Tomcat 目前只是Web 容器,它不能運(yùn)行EJB 應(yīng)用。,什么是JNDI,JNDI 是自JDK1.3 版本開(kāi)始就綁定的標(biāo)準(zhǔn)Java API。它為各種現(xiàn)有的命名和目錄服務(wù)提供了通用接口:DNS、LDAP、活動(dòng)目錄(Active Directory)、RMI 注冊(cè)器、COS 注冊(cè)器、NIS 及文件系統(tǒng)。在結(jié)構(gòu)上,JNDI 由兩部分組成:客戶(hù)API 和服務(wù)提供商接口(Service Provider Intergace,SPI),應(yīng)用程序通過(guò)客戶(hù)API 訪問(wèn)命名和目錄服務(wù);服務(wù)提供商接口用于供廠商創(chuàng)建命名和目錄服務(wù)的JNDI 實(shí)現(xiàn)。

5、下面是JNDI 的結(jié)構(gòu)圖:,什么是JNDI,什么是JNDI,對(duì)于EJB 開(kāi)發(fā)者來(lái)說(shuō),我們只需要知道使用客戶(hù)API 如何訪問(wèn)命名和目錄服務(wù)即可,而不需要知道JNDI SPI 的使用,因?yàn)槲覀儾恍枰褂肑NDI SPI 開(kāi)發(fā)JNDI 實(shí)現(xiàn)產(chǎn)品,這就好比通過(guò)JDBC 訪問(wèn)數(shù)據(jù)庫(kù),我們只需要知道使用JDBC API 如何訪問(wèn)數(shù)據(jù)庫(kù),而不需要知道數(shù)據(jù)庫(kù)的JDBC 驅(qū)動(dòng)如何實(shí)現(xiàn)。使用客戶(hù)API 訪問(wèn)EJB3.0,我們需要編寫(xiě)的JNDI 代碼不過(guò)幾句,所以大家不要被嚇倒了。 命名服務(wù)用于將名稱(chēng)和對(duì)象聯(lián)系起來(lái),使得我們可以用名稱(chēng)訪問(wèn)對(duì)象。例如,當(dāng)你在web 瀏覽器輸入U(xiǎn)RL: 時(shí),DNS(Domain Nam

6、e System,域名系統(tǒng))將這個(gè)域名轉(zhuǎn)換成IP 地址。 目錄服務(wù)是命名服務(wù)的自然擴(kuò)展,在這種服務(wù)里,對(duì)象不但有名稱(chēng),還有屬性。與命名服務(wù)的關(guān)鍵差別是:目錄服務(wù)中對(duì)象可以有屬性(例如,用戶(hù)有email 地址),而命名服務(wù)中對(duì)象沒(méi)有屬性。,下載與安裝JDK,進(jìn)入 下載JDK。在頁(yè)面中找到JDK 5.0 Update 14(版本在不斷更新中,有可能大于14),點(diǎn)擊右邊的Download,注意中間有Accept 和Decline 兩選項(xiàng),點(diǎn)選Accept。在Windows Platform 一欄找到Windows Offline Installation, Multi-language 這個(gè)鏈接,點(diǎn)

7、擊下載。(注:本書(shū)光盤(pán)“軟件”文件夾中帶有JDK 5.0) 按照安裝向?qū)崾景惭b,安裝路徑選擇C:Javajdk1.5.0_14。Jdk 安裝完后,接著問(wèn)你是否安裝jre,也一起安裝上。 右鍵點(diǎn)擊“我的電腦”-“屬性”-“高級(jí)”-“環(huán)境變量”,在“系統(tǒng)變量”里添加JAVA_HOME 變量,值為JDK 的安裝路徑,如:C: Javajdk1.5.0_14。 在“系統(tǒng)變量”里再添加CLASSPATH 變量,值為:.; %JAVA_HOME%libdt.jar; %JAVA_HOME%libtools.jar;在系統(tǒng)變量欄找到變量名為Path 的選項(xiàng),點(diǎn)“編輯”在變量值的末尾添加;%JAVA_HOM

8、E%bin;,下載與安裝jboss,進(jìn)入 文件下載(大小為92MB)。下載后直接解壓縮文件即可完成安裝,為了避免應(yīng)用出現(xiàn)莫名的錯(cuò)誤,解壓縮的路徑最好不要帶有空格,如“Program Files”。 安裝完后請(qǐng)右鍵點(diǎn)擊“我的電腦”-“屬性”-“高級(jí)”-“環(huán)境變量”,在“系統(tǒng)變量”里添加JBOSS_HOME變量,值為Jboss 的安裝路徑,如:D:JavaEEServerjboss。 在系統(tǒng)變量一欄找到變量名為Path 的選項(xiàng),點(diǎn)“編輯”在變量值的末尾添加:;%JBOSS_HOME%bin;現(xiàn)在驗(yàn)證Jboss 安裝是否成功, 進(jìn)入jboss 安裝目錄bin 目錄,雙擊run.bat 啟動(dòng)jboss

9、。觀察控制臺(tái)有沒(méi)有Java例外拋出,如果沒(méi)有例外并看到下圖,恭喜你,安裝成功了。,啟動(dòng)jboss,啟動(dòng)jboss,你可以輸入http:/localhost:8080 進(jìn)入Jboss 的歡迎主頁(yè)。在JBoss Management 欄點(diǎn)擊“JMX Console”進(jìn)入Jboss的管理平臺(tái)。如果需要輸入用戶(hù)名及密碼,默認(rèn)的用戶(hù)名及密碼都是admin。 如果jboss 啟動(dòng)出錯(cuò),應(yīng)檢查打印在Jboss 控制臺(tái)的JDK 版本是否5.0 以上,jboss 所用的端口是否被占用(如1099,8009 ,8080 等端口)。如果端口被占用就關(guān)閉占用此端口的進(jìn)程。 如果啟動(dòng)時(shí)出現(xiàn)這樣的錯(cuò)誤:“findstr

10、不是內(nèi)部或外部命令,也不是可運(yùn)行的程序或批處理文件”。那么應(yīng)該在系統(tǒng)變量Path 中追加%SystemRoot%system32;%SystemRoot%;。 最后的辦法是重裝機(jī)器上的JDK,祝你好運(yùn)。,運(yùn)行第一個(gè)EJB3 例子,在本書(shū)配套光盤(pán)的HelloWorld 文件夾下,找到HelloWorld.jar,把該文件拷貝到“jboss 安裝目錄/server/default/deploy/”目錄下,jboss 會(huì)對(duì)HelloWorld 進(jìn)行熱部署。接下來(lái)繼續(xù)把EJBTest文件夾下的EJBTest.war 拷貝到“jboss 安裝目錄/server/default/deploy/。 在瀏覽器

11、上輸入:http:/localhost:8080/EJBTest/Test.jsp(注意大小寫(xiě))。將會(huì)看見(jiàn)下圖所示。,運(yùn)行第一個(gè)EJB3 例子,在JBoss 部署應(yīng)用,在JBoss 部署應(yīng)用的過(guò)程非常簡(jiǎn)單、直接。在每一個(gè)配置中,Jboss 會(huì)不斷掃描一個(gè)名為jboss 安裝目錄/server/config-name/deploy 的特定目錄,查看是否有任何更新,此目錄一般被稱(chēng)為“部署目錄”。 你可以把下列文件拷貝到部署目錄中: 任何Java 庫(kù)(其中的類(lèi)將被自動(dòng)添加到JBoss 的classpath 中) EJB-JAR WAR (Web Appliction aRrchive) EAR (E

12、nterprise Application aRchive) 包含JBoss MBean 定義的XML 文件 以.jar、.war 或者.ear 結(jié)尾的目錄,分別包含了EJB-JAR、WAR 或者EAR 的解壓縮內(nèi)容。 要重新部署上述文件(JAR、WAR、EAR、XML 等),只需用更新后的版本覆蓋即可。Jboss 將通過(guò)對(duì)比時(shí)間戳來(lái)檢測(cè)變化,卸載舊文件,部署相應(yīng)的新文件。如果要重新部署目錄,只需更新其時(shí)間戳即可。從部署目錄中刪除文件會(huì)導(dǎo)致相應(yīng)文件從部署中卸載。,會(huì)話(huà)Bean(Session Bean),Session Bean 是實(shí)現(xiàn)業(yè)務(wù)邏輯的地方。簡(jiǎn)單地說(shuō),像我們要實(shí)現(xiàn)兩數(shù)相加或是從數(shù)據(jù)庫(kù)

13、中讀取數(shù)據(jù),都是通過(guò)Session Bean 來(lái)實(shí)現(xiàn)。根據(jù)是否可以維護(hù)會(huì)話(huà)狀態(tài),Session Bean 分為有狀態(tài)bean 和無(wú)狀態(tài)bean。有狀態(tài)bean 可以維護(hù)會(huì)話(huà)狀態(tài),無(wú)狀態(tài)bean 不維護(hù)會(huì)話(huà)狀態(tài)。要維護(hù)會(huì)話(huà)狀態(tài),意味著EJB 容器要為每個(gè)用戶(hù)創(chuàng)建一個(gè)bean實(shí)例,并通過(guò)該實(shí)例保存著與用戶(hù)的會(huì)話(huà)狀態(tài)。不維護(hù)會(huì)話(huà)狀態(tài),意味著一個(gè)bean 實(shí)例不需要保存與某個(gè)用戶(hù)的會(huì)話(huà)狀態(tài),這時(shí)一個(gè)bean 實(shí)例可以為多個(gè)用戶(hù)服務(wù)。,會(huì)話(huà)Bean(Session Bean),要開(kāi)發(fā)一個(gè)Session Bean,我們需要定義接口和Bean class。其中接口分為遠(yuǎn)程(remote)和本地(local)

14、接口。在EJB3.0中,不要求你同時(shí)實(shí)現(xiàn)remote 和local 接口,但實(shí)現(xiàn)兩者是比較好的做法。 遠(yuǎn)程接口(remote interface):定義了session bean 的業(yè)務(wù)方法,這些方法可以被來(lái)自EJB 容器之外的應(yīng)用訪問(wèn)到。 本地接口(local interface):同樣定義了session bean 的業(yè)務(wù)方法,這些方法可以被同處于EJB 容器內(nèi)的其它應(yīng)用使用。因?yàn)閘ocal 接口允許bean 之間直接通過(guò)內(nèi)存交互,沒(méi)有分布式對(duì)象協(xié)議的開(kāi)銷(xiāo),從而改善了性能。 Bean 類(lèi)(bean class):bean class 包含了業(yè)務(wù)邏輯,它必須具備一個(gè)遠(yuǎn)程或本地接口。在Bean

15、 類(lèi),我們應(yīng)該實(shí)現(xiàn)接口的業(yè)務(wù)方法,盡管這并不是必須的,但我們沒(méi)理由不這樣做。,Stateless Session Beans(無(wú)狀態(tài)bean)開(kāi)發(fā),由于無(wú)狀態(tài)會(huì)話(huà)Bean 不維護(hù)會(huì)話(huà)狀態(tài),意味著一個(gè)bean 實(shí)例可以為多個(gè)用戶(hù)服務(wù)。因此EJB 容器使用實(shí)例池化技術(shù)管理無(wú)狀態(tài)會(huì)話(huà)Bean。簡(jiǎn)單的說(shuō)就是:當(dāng)無(wú)狀態(tài)會(huì)話(huà)Bean 部署到應(yīng)用服務(wù)器時(shí),EJB 容器會(huì)為它預(yù)先創(chuàng)建一些bean 實(shí)例放在對(duì)象池。當(dāng)有用戶(hù)訪問(wèn)EJB 方法時(shí),EJB 容器會(huì)從對(duì)象池中取出一個(gè)實(shí)例為之服務(wù),服務(wù)完了就回到對(duì)象池。當(dāng)下一個(gè)用戶(hù)再訪問(wèn)EJB 方法時(shí),EJB 容器有可能再次把該實(shí)例取出來(lái)為之服務(wù)。正因如此,無(wú)狀態(tài)會(huì)話(huà)Be

16、an 只需要少量的實(shí)例就可以為成百上千的用戶(hù)服務(wù),大大提高了系統(tǒng)性能。 由于無(wú)狀態(tài)會(huì)話(huà)Bean 能夠支持多個(gè)用戶(hù),并且通常在EJB 容器中共享,可以為需要大量客戶(hù)的應(yīng)用提供更好的擴(kuò)充能力。無(wú)狀態(tài)會(huì)話(huà)Bean 比有狀態(tài)會(huì)話(huà)Bean 更具性能優(yōu)勢(shì),在條件允許的情況下開(kāi)發(fā)人員應(yīng)該首先考慮使用無(wú)狀態(tài)會(huì)話(huà)Bean。,開(kāi)發(fā)只實(shí)現(xiàn)Remote 接口的無(wú)狀態(tài)Session Bean,在開(kāi)發(fā)前,先熟悉一下本例子的調(diào)用流程圖:,例子的開(kāi)發(fā),現(xiàn)在我們就開(kāi)始本例子的開(kāi)發(fā)。首先在Eclipse 中新建一個(gè)普通的java 項(xiàng)目,然后把Jboss 安裝目錄/client 下的所有jar 文件加入到項(xiàng)目的構(gòu)建路徑中。如果不需

17、要在項(xiàng)目中使用單元測(cè)試用例或普通J2SE 調(diào)用EJB,你只需要加入javaee.jar,接下來(lái)開(kāi)始代碼編寫(xiě)。,開(kāi)發(fā)步驟,第一步:定義一個(gè)包含業(yè)務(wù)方法的接口。這個(gè)接口不需要包含任何注釋?zhuān)且粋€(gè)普通的java 接口。調(diào)用EJB的客戶(hù)端使用這個(gè)接口引用從EJB 容器返回的存根(stub)。代碼如下: HelloWorld.java package com.foshanshop.ejb3; public interface HelloWorld public String SayHello(String name); ,開(kāi)發(fā)步驟,第二步:編寫(xiě)B(tài)ean class。 HelloWorldBean.ja

18、va 。Bean 類(lèi)推薦的命名方式是:接口+Bean ,如: HelloWorldBean 。 package com.foshanshop.ejb3.impl; import com.foshanshop.ejb3.HelloWorld; import javax.ejb.Remote; import javax.ejb.Stateless; Stateless Remote (HelloWorld.class) public class HelloWorldBean implements HelloWorld public String SayHello(String name) retu

19、rn name +說(shuō):你好!世界,這是我的第一個(gè)EJB3哦.; ,Stateless 注釋,在Bean 類(lèi)上面有兩個(gè)注釋Stateless 和Remote,Stateless 注釋指明這是一個(gè)無(wú)狀態(tài)會(huì)話(huà)Bean。Stateless 注釋的定義如下: Package javax.ejb; Target(TYPE) Retention(RUNTIME) public interface Stateless String name( ) default ; String mappedName() default ; name()屬性用于指定session bean 的EJB 名稱(chēng)。該名稱(chēng)在EJB J

20、ar 包中必須是全局唯一的,而在EAR 中卻可以重復(fù)(因?yàn)镋AR 可以包含多個(gè)EJB Jar,而每個(gè)jar 可以存在一個(gè)同名的EJB,在EAR 中要定位某個(gè)EJB,可以這樣使用:xxx.jar#HelloWorldBean)。如果不指定該屬性,默認(rèn)就是bean class 的非限定名稱(chēng)。對(duì)本例而言,EJB 名稱(chēng)默認(rèn)為HelloWorldBean。 mappedName()屬性指定Bean 的全局JNDI 名稱(chēng),這個(gè)屬性在weblogic,Sun 應(yīng)用服務(wù)器和glassfish 起作用。,Remote 注釋,Remote 注釋指定這個(gè)無(wú)狀態(tài)Bean 的remote 接口。Bean 類(lèi)可以具有多個(gè)

21、remote 接口,每個(gè)接口之間用逗號(hào)分隔,如:Remote (HelloWorld.class,Hello.class,World.class)。如果你只有一個(gè)接口,你可以省略大括號(hào),對(duì)于本例而言,可以寫(xiě)成這樣:Remote (HelloWorld.class)。 經(jīng)過(guò)上面兩步,一個(gè)HelloWorld EJB 就開(kāi)發(fā)完了?,F(xiàn)在我們把它發(fā)布到Jboss 中。在發(fā)布前我們需要把它打成Jar包。打JAR 包的方法有很多,如使用jar 命令、集成開(kāi)發(fā)工具或者Ant。,Eclipse 打包向?qū)?在Eclipse 開(kāi)發(fā)環(huán)境下,可以通過(guò)導(dǎo)出向?qū)нM(jìn)行打包。在項(xiàng)目名稱(chēng)上點(diǎn)擊右鍵,在跳出的菜單中選擇“Expo

22、rt(導(dǎo)出)”,在“Export”對(duì)話(huà)框選擇“JAR file”,如下圖:,Eclipse 打包向?qū)?點(diǎn)“Next”,在“select the resources to export(選擇要導(dǎo)出的資源)”一欄,展開(kāi)你的項(xiàng)目并選擇需要打包的文件。然后選擇一個(gè)存放目錄及文件名。點(diǎn)“Finish”結(jié)束打包。如下圖:,例子發(fā)布,當(dāng)HelloWorld 打成jar 文件后,我們把它發(fā)布到Jboss。發(fā)布前先檢查jboss 是否已經(jīng)啟動(dòng),如果沒(méi)有啟動(dòng),我們可以進(jìn)入jboss 安裝目錄/bin,雙擊run.bat 啟動(dòng)Jboss。不指定啟動(dòng)參數(shù)的情況下,Jboss 默認(rèn)使用default 配置項(xiàng)。 把jar

23、 文件拷貝到j(luò)boss 安裝目錄serverdefaultdeploy目錄。觀察Jboss 控制臺(tái)輸出,如果沒(méi)有拋出例外并看到下面的輸出界面,發(fā)布就算成功了。,查看JNDI,當(dāng)EJB 發(fā)布成功后,Jboss 容器會(huì)為它生成一個(gè)全局JNDI 名稱(chēng),我們可以利用這一點(diǎn)進(jìn)一步判斷EJB 發(fā)布是否成功。我們進(jìn)入Jboss 的管理臺(tái)查看它的JNDI 名稱(chēng),輸入下面URL http:/localhost:8080/jmx-console/ 點(diǎn)擊service=JNDIView,查看EJB 的JNDI 名稱(chēng)。(如下圖),查看JNDI,在出現(xiàn)的頁(yè)面中,找到“List of MBean operations:”

24、欄。(如下圖),查看JNDI,點(diǎn)擊“Invoke”按鈕,出現(xiàn)如下界面:,查看JNDI,在出現(xiàn)的頁(yè)面中,我們可以看到JBOSS 的JNDI 樹(shù),它的命名約定如下: (1)java:comp (java:comp namespace) 這個(gè)上下文環(huán)境和其子上下文環(huán)境僅能被應(yīng)用組件內(nèi)部訪問(wèn)和使用 (2)java:(java: Namespace) 上下文環(huán)境和綁定的對(duì)象只能被處在同一個(gè)JVM 內(nèi)的客戶(hù)訪問(wèn) (3)Global JNDI Namespace 上下文環(huán)境能被所有客戶(hù)訪問(wèn),不管它們是否處在同一個(gè)JVM 內(nèi)。,Jbos默認(rèn)的JNDI命名規(guī)則,當(dāng)EJB 發(fā)布到Jboss 時(shí),如果我們沒(méi)有為它指

25、定全局JNDI 名稱(chēng)或修改過(guò)其默認(rèn)EJB 名稱(chēng),Jboss 就會(huì)按照默認(rèn)的命名規(guī)則為EJB 生成全局JNDI 名稱(chēng),默認(rèn)的命名規(guī)則如下: 如果把EJB 作為模塊打包進(jìn)后綴為*.ear 的JAVA EE 企業(yè)應(yīng)用文件,默認(rèn)的全局JNDI 名稱(chēng)是 本地接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/local 遠(yuǎn)程接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/remote EAR-FILE-BASE-NAME 為ear 文件的名稱(chēng),EJB-CLASS-NAME 為EJB 的非限定類(lèi)名。 例:把HelloWorld 應(yīng)用作為EJB 模塊打包進(jìn)名為

26、HelloWorld.ear 的企業(yè)應(yīng)用文件,它的遠(yuǎn)程接口的JNDI 名稱(chēng)是: HelloWorld/HelloWorldBean/remote 如果把EJB 應(yīng)用打包成后綴為*.jar 的模塊文件,默認(rèn)的全局JNDI 名稱(chēng)是 本地接口:EJB-CLASS-NAME/local 遠(yuǎn)程接口:EJB-CLASS-NAME/remote 例:把HelloWorld 應(yīng)用打包成HelloWorld.jar 文件,它的遠(yuǎn)程接口的JNDI 名稱(chēng)是:HelloWorldBean/remote 注意:EJB-CLASS-NAME 是不帶包名的,如com.foshanshop.ejb3.impl.HelloWo

27、rldBean 只需取HelloWorldBean。 如果你通過(guò)S()、S()及其等價(jià)的XML 指定了EJB 名稱(chēng),那么上面的EJB-CLASS-NAME應(yīng)該換為EJB 名稱(chēng),此時(shí)的JNDI 名稱(chēng)格式如:EJB 名稱(chēng)/remote、EAR 文件名/EJB 名稱(chēng)/remote。,訪問(wèn)例子EJB,在Global JNDI Namespace 一欄,我們看到了HelloWorldBean 的遠(yuǎn)程接口的JNDI 名稱(chēng)為HelloWorldBean/remote。意味著EJB 已經(jīng)發(fā)布成功。接下來(lái)我們看看客戶(hù)端如何訪問(wèn)它。 Test.jsp ,訪問(wèn)例子E

28、JB,在進(jìn)行JNDI 查找前,我們必須設(shè)置應(yīng)用服務(wù)器的上下文信息,主要是設(shè)置JNDI 驅(qū)動(dòng)的類(lèi)名(java.naming.factory.initial)和命名服務(wù)提供者的URL (vider.url) 。 java.naming.factory.initial 或Context.INITIAL_CONTEXT_FACTORY:環(huán)境屬性名,用于指定InitialContext工廠(作者稱(chēng)它為JNDI 驅(qū)動(dòng)更容易理解),它類(lèi)似于JDBC 指定數(shù)據(jù)庫(kù)驅(qū)動(dòng)類(lèi)。 因?yàn)楸纠舆B接的是JbossNS(命名服務(wù)的實(shí)現(xiàn)者),所以使用Jboss 提供的驅(qū)動(dòng)類(lèi): org.jnp.in

29、terfaces.NamingContextFactory vider.url 或Context.PROVIDER_URL:環(huán)境屬性名,包含提供命名服務(wù)的主機(jī)地址和端口號(hào)。它類(lèi)似于JDBC 指定數(shù)據(jù)庫(kù)的連接URL。 連接到JbossNS 的URL 格式為:jnp:/host:port,該URL 的“jnp:”部分是指使用的協(xié)議,JBoss 使用的是基于Socket/RMI 的協(xié)議。host 為主機(jī)的地址,port 為JNDI 服務(wù)的端口。除了host 之外,其他部分都是可以不寫(xiě)的。 除了上述兩個(gè)環(huán)境屬性外,還有兩個(gè)環(huán)境屬性是我們經(jīng)常使用到的:java.naming

30、.security.principal(或Context.SECURITY_PRINCIPAL)和java.naming.security.credentials(或Context.SECURITY_CREDENTIALS),這兩個(gè)環(huán)境屬性用于指定用戶(hù)標(biāo)識(shí)(如用戶(hù)名)及憑證(如密碼),當(dāng)EJB 使用了安全服務(wù)時(shí),你必須提供這兩個(gè)屬性。它類(lèi)似于JDBC 指定連接到數(shù)據(jù)庫(kù)的用戶(hù)名及密碼。,上下文環(huán)境,如果客戶(hù)端運(yùn)行在應(yīng)用服務(wù)器內(nèi),我們不需要為InitialContext 設(shè)置應(yīng)用服務(wù)器的上下文信息,也不建議設(shè)置。因?yàn)閼?yīng)用服務(wù)器啟動(dòng)時(shí)會(huì)把JNDI 驅(qū)動(dòng)類(lèi)等上下文信息添加進(jìn)系統(tǒng)屬性,創(chuàng)建Initial

31、Context 對(duì)象時(shí)如果沒(méi)有指定Properties 參數(shù),InitialContext 內(nèi)部會(huì)調(diào)用System.getProperty()方法從系統(tǒng)屬性里獲取必要的上下文信息。對(duì)本例子而言,你可以省略傳入props 參數(shù)。在實(shí)際應(yīng)用中,如果給InitialContext 設(shè)置了參數(shù),反而會(huì)帶來(lái)不可移植的問(wèn)題。,上下文環(huán)境,創(chuàng)建InitialContext 對(duì)象時(shí)如果沒(méi)有指定Properties 參數(shù),InitialContext 還會(huì)在classpath 下尋找perties文件,并從該文件中加載應(yīng)用服務(wù)器的上下文信息。這樣避免了硬編碼為InitialContext 設(shè)置P

32、roperties 參數(shù)。 perties 的配置如下: java.naming.factory.initial=erfaces.NamingContextFactory vider.url=localhost:1099 java.naming.factory.url.pkgs=org.jboss.naming:erfaces 當(dāng)InitialContext 初始化后,我們使用EJB 的Jndi 名稱(chēng)通過(guò)lookup()方法查找EJB。lookup()方法返回一個(gè)存根對(duì)象,該存根實(shí)現(xiàn)了HelloWorld

33、 接口。它負(fù)責(zé)將方法調(diào)用路由到應(yīng)用服務(wù)器,應(yīng)用服務(wù)器再把方法調(diào)用請(qǐng)求路由到HelloWorldBean 實(shí)例。,開(kāi)發(fā)只實(shí)現(xiàn)Local 接口的無(wú)狀態(tài)Session Bean,開(kāi)發(fā)只有Local接口的無(wú)狀態(tài)Session Bean的步驟和上節(jié)開(kāi)發(fā)只有Remote接口的無(wú)狀態(tài)會(huì)話(huà)Bean的步驟相同,兩者唯一不同之處是,前者使用Remote注釋聲明接口是遠(yuǎn)程接口,后者使用Local注釋聲明接口是本地接口。 當(dāng)Local和Remote注釋都不存在時(shí),容器會(huì)將Bean class實(shí)現(xiàn)的接口默認(rèn)為L(zhǎng)ocal接口。如果EJB與客戶(hù)端部署在同一個(gè)應(yīng)用服務(wù)器,采用Local接口訪問(wèn)EJB優(yōu)于Remote接口。因?yàn)?/p>

34、通過(guò)Remote接口訪問(wèn)EJB需要在tcp/ip協(xié)議基礎(chǔ)上轉(zhuǎn)換和解釋Corba IIOP協(xié)議消息,在調(diào)用EJB的這一過(guò)程中存在對(duì)象序列化,協(xié)議解釋、tcp/ip通信等開(kāi)銷(xiāo)。而通過(guò)Local接口訪問(wèn)EJB是在內(nèi)存中與bean彼此交互的,沒(méi)有了分布式對(duì)象協(xié)議的開(kāi)銷(xiāo),大大改善了性能。下面是只有Local接口的無(wú)狀態(tài)會(huì)話(huà)Bean。,業(yè)務(wù)接口和Bean類(lèi),業(yè)務(wù)接口:LocalHelloWorld.java package com.foshanshop.ejb3; public interface LocalHelloWorld public String SayHello(String name); B

35、ean 類(lèi):LocalHelloWorldBean.java package com.foshanshop.ejb3.impl; import javax.ejb.Local; import javax.ejb.Stateless; import com.foshanshop.ejb3.LocalHelloWorld; Stateless Local (LocalHelloWorld.class) public class LocalHelloWorldBean implements LocalHelloWorld public String SayHello(String name) ret

36、urn name +說(shuō):你好!世界,這是一個(gè)只具有Local接口的無(wú)狀態(tài)Bean; ,客戶(hù)端代碼,把上面的EJB 打成jar 文件后,發(fā)布到j(luò)boss 安裝目錄serverdefaultdeploy 目錄中。接下來(lái)我們編寫(xiě)客戶(hù)端調(diào)用代碼。 LocalSessionBeanTest.jsp ,開(kāi)發(fā)實(shí)現(xiàn)了Remote 與Local 接口的無(wú)狀態(tài)Session Bean,在實(shí)際應(yīng)用中,同時(shí)實(shí)現(xiàn)Remote 與Local 接口是一種比較好的做法。這樣你既可以在遠(yuǎn)程訪問(wèn)EJB,也可以在本地訪問(wèn)EJB。 遠(yuǎn)程接口:Operation.java package com.foshanshop.ejb3; pu

37、blic interface Operation public int Addup(); 本地接口:LocalOperation.java,本地接口繼承了遠(yuǎn)程接口的所有方法 package com.foshanshop.ejb3; public interface LocalOperation extends Operation ,會(huì)話(huà)Bean:OperationBean.java,package com.foshanshop.ejb3.impl; import javax.ejb.Local; import javax.ejb.Remote; import javax.ejb.Statele

38、ss; import com.foshanshop.ejb3.LocalOperation; import com.foshanshop.ejb3.Operation; Stateless Remote (Operation.class) Local (LocalOperation.class) public class OperationBean implements Operation, LocalOperation private int total = 0; public int Addup() total+; return total; ,JSP 客戶(hù)端:OperationBeanT

39、est.jsp, (通過(guò)遠(yuǎn)程接口調(diào)用EJB)累加的結(jié)果是:+ remote.Addup(); catch (Exception e) out.println(遠(yuǎn)程接口調(diào)用失敗); out.println(=); try /通過(guò)本地接口調(diào)用EJB LocalOperation local = (LocalOperation) ctx.lookup(OperationBean/local); out.println(通過(guò)本地接口調(diào)用EJB)累加的結(jié)果是:+ local.Addup(); catch (Exception e) out.println(本地接口調(diào)用失敗); %,執(zhí)行結(jié)果,把EJB 及

40、客戶(hù)端應(yīng)用打包后發(fā)布到j(luò)boss 中,第一次執(zhí)行客戶(hù)端的結(jié)果如下:,大家可能會(huì)發(fā)現(xiàn)在通過(guò)local 接口調(diào)用EJB 的地方,累加的結(jié)果為2。怎么會(huì)為2,明明是第一次調(diào)用嘛,應(yīng)該是1 才對(duì)呀? 這是因?yàn)镾tateless Session Bean 不負(fù)責(zé)維護(hù)會(huì)話(huà)狀態(tài),Stateless Session Bean 一旦實(shí)例化就被加進(jìn)實(shí)例池中,各個(gè)用戶(hù)都可以共用。即使用戶(hù)已經(jīng)消亡,Stateless Session Bean 的生命期也不一定結(jié)束,它可能依然存在于實(shí)例池中,供其他用戶(hù)使用。如果它有自己的屬性(變量),那么這些變量就會(huì)受到所有使用它的用戶(hù)影響。,Stateful Session Bea

41、n(有狀態(tài)bean)開(kāi)發(fā),stateless session bean 創(chuàng)建在對(duì)象池中,提供給眾多用戶(hù)使用,如果Bean class 有自己的成員屬性(變量),那么這些變量就會(huì)受到所有調(diào)用它的用戶(hù)影響。在一些應(yīng)用場(chǎng)合中,有時(shí)我們需要每個(gè)用戶(hù)都有自己的一個(gè)實(shí)例,這個(gè)實(shí)例不受其他用戶(hù)影響。就好比購(gòu)物車(chē)對(duì)象,每個(gè)用戶(hù)都應(yīng)有自己的購(gòu)物車(chē),你不希望有人往你的購(gòu)物車(chē)?yán)锾砑踊蚰玫羯唐?,而有狀態(tài)Bean 正好滿(mǎn)足你的這種需求。每個(gè)有狀態(tài)Bean 在bean 實(shí)例的生命周期內(nèi)都只服務(wù)于一個(gè)用戶(hù),bean class 的成員變量可以在不同的方法調(diào)用間維護(hù)特定于某個(gè)用戶(hù)的數(shù)據(jù)。正因?yàn)樵赽ean 實(shí)例的生命周期內(nèi),S

42、tateful Session Bean 保持了用戶(hù)的信息,所以叫有狀態(tài)Bean。,Stateful Session Bean(有狀態(tài)bean)開(kāi)發(fā),stateless session bean 創(chuàng)建在對(duì)象池中,提供給眾多用戶(hù)使用,如果Bean class 有自己的成員屬性(變量),那么這些變量就會(huì)受到所有調(diào)用它的用戶(hù)影響。在一些應(yīng)用場(chǎng)合中,有時(shí)我們需要每個(gè)用戶(hù)都有自己的一個(gè)實(shí)例,這個(gè)實(shí)例不受其他用戶(hù)影響。就好比購(gòu)物車(chē)對(duì)象,每個(gè)用戶(hù)都應(yīng)有自己的購(gòu)物車(chē),你不希望有人往你的購(gòu)物車(chē)?yán)锾砑踊蚰玫羯唐?,而有狀態(tài)Bean 正好滿(mǎn)足你的這種需求。每個(gè)有狀態(tài)Bean 在bean 實(shí)例的生命周期內(nèi)都只服務(wù)于一個(gè)

43、用戶(hù),bean class 的成員變量可以在不同的方法調(diào)用間維護(hù)特定于某個(gè)用戶(hù)的數(shù)據(jù)。正因?yàn)樵赽ean 實(shí)例的生命周期內(nèi),Stateful Session Bean 保持了用戶(hù)的信息,所以叫有狀態(tài)Bean。,業(yè)務(wù)接口:Cart.java,package com.foshanshop.ejb3; import java.io.Serializable; import java.util.List; public interface Cart extends Serializable public void AddBuyItem(String productName); public List g

44、etBuyItem(); ,Bean 類(lèi):CartBean.java,SuppressWarnings(serial) Stateful Remote(Cart.class) public class CartBean implements Cart private List buyitem = new ArrayList(); public void AddBuyItem(String productName) buyitem.add(productName); public List getBuyItem() return buyitem; Stateful 注釋指明這是一個(gè)有狀態(tài)會(huì)話(huà)Be

45、an,Remote 注釋指定有狀態(tài)Bean 的remote 接口。 SuppressWarnings(serial) 注釋屏蔽缺少serialVersionUID 定義警告。,JSP 客戶(hù)端代碼:StatefulBeanTest.jsp, buyitem = cat.getBuyItem(); out.println(購(gòu)物車(chē)的商品列表:); for(String name : buyitem) out.println( + name+ ); catch (Exception e) out.println(e.getMessage(); %,在JSP 代碼中,先試圖從session 中獲取購(gòu)物車(chē)

46、的存根。如果當(dāng)前session 不存在購(gòu)物車(chē),就創(chuàng)建一個(gè)新的購(gòu)物車(chē)放入session 中。后面每執(zhí)行一次頁(yè)面都會(huì)添加一個(gè)相同的商品。,改變Session Bean 的JNDI 名稱(chēng),需要自定義JNDI 名稱(chēng)時(shí),如果EJB 在Jboss 中使用,可以使用Jboss 提供的LocalBinding 和RemoteBinding 注釋?zhuān)琇ocalBinding 注釋指定Session Bean 的Local 接口的JNDI 名稱(chēng),RemoteBinding 注釋指定Session Bean 的Remote 接口的JNDI名稱(chēng),如下: Remote (Operation.class) RemoteBi

47、nding (jndiBinding=foshanshop/RemoteOperation) Local (LocalOperation.class) LocalBinding (jndiBinding=foshanshop/LocalOperation) public class OperationBean implements Operation, LocalOperation ,客戶(hù)端代碼片斷,InitialContext ctx = new InitialContext(props); Operation operation = (Operation)ctx.lookup(foshan

48、shop/RemoteOperation); LocalBinding 和RemoteBinding 注釋只是針對(duì)jboss , 如果你使用的是weblogic10/Sun Application Server/Glassfish,你可以使用Stateless.mappedName()設(shè)置bean 的全局JNDI 名稱(chēng),如: Stateless(mappedName=OperationBeanRemote) public class OperationBean implements Operation, LocalOperation 客戶(hù)端訪問(wèn)EJB 的代碼片斷如下: InitialConte

49、xt ctx = new InitialContext(props); Operation operation = (Operation) ctx.lookup(OperationBeanRemote#com.foshanshop.ejb3.Operation);,JNDI移植問(wèn)題,由于JNDI名稱(chēng)與廠商有關(guān),如果使用注釋定義JNDI名稱(chēng)會(huì)帶來(lái)移植問(wèn)題,因此建議使用ejb-jar.xml部署描述文件進(jìn)行定義,該文件必須放置在jar的META-INF目錄下 HelloWorldBean HelloWorldBean ,Session Bean 的生命周期事件,前面我們已經(jīng)對(duì)Stateless S

50、ession Bean 和stateful session bean 的生命周期有所了解。在Session bean 的生命周期里,狀態(tài)變化會(huì)觸發(fā)生命周期事件的發(fā)生。如從does not exist 狀態(tài)進(jìn)入method-ready pool 狀態(tài)會(huì)觸發(fā)PostConstruct 事件。同樣從method-ready pool 狀態(tài)進(jìn)入does not exist 狀態(tài)也會(huì)觸發(fā)PreDestroy 事件。 有些時(shí)候,你需要定制session bean 的管理過(guò)程。例如,你可能想在創(chuàng)建session bean 實(shí)例的時(shí)候初始化字段變量,或在bean 實(shí)例被銷(xiāo)毀的時(shí)候關(guān)掉外部資源。上述這些,你都可

51、能通過(guò)在bean 類(lèi)定義生命周期的回調(diào)方法來(lái)實(shí)現(xiàn)。 這些方法將會(huì)被容器在生命周期的不同階段調(diào)用(如:創(chuàng)建或銷(xiāo)毀)。通過(guò)使用下面的注釋?zhuān)珽JB 3.0 允許你將任何方法指定為回調(diào)方法。這不同于EJB 2.1,所有的回調(diào)方法必須實(shí)現(xiàn),即使是空的。在EJB 3.0,bean 可以有任意數(shù)量,任意名字的回調(diào)方法。,生命周期事件,PostConstruct:當(dāng)bean 對(duì)象完成實(shí)例化后,標(biāo)注了這個(gè)注釋的方法會(huì)被立即調(diào)用,每個(gè)bean class 只能定義一個(gè)PostConstruct 方法。這個(gè)注釋同時(shí)適用于有狀態(tài)和無(wú)狀態(tài)會(huì)話(huà)bean。 PreDestroy:標(biāo)注了這個(gè)注釋的方法會(huì)在容器銷(xiāo)毀一個(gè)無(wú)用的或

52、者過(guò)期的bean 實(shí)例之前調(diào)用。這個(gè)注釋同時(shí)適用于有狀態(tài)和無(wú)狀態(tài)會(huì)話(huà)bean。 PrePassivate:當(dāng)一個(gè)有狀態(tài)的bean 實(shí)例空閑時(shí)間過(guò)長(zhǎng),就會(huì)發(fā)生鈍化(passivate)。標(biāo)注了這個(gè)注釋的方法會(huì)在鈍化之前被調(diào)用。bean 實(shí)例被鈍化后,在一段時(shí)間內(nèi),如果仍然沒(méi)有用戶(hù)對(duì)bean 實(shí)例進(jìn)行操作,容器將會(huì)從硬盤(pán)中刪除它。以后,任何針對(duì)該bean 方法的調(diào)用,容器都會(huì)拋出例外。這個(gè)注釋適用于有狀態(tài)會(huì)話(huà)bean。,生命周期事件,PostActivate:當(dāng)客戶(hù)端再次使用已經(jīng)被鈍化的有狀態(tài)bean 時(shí),EJB 容器會(huì)重新實(shí)例化一個(gè)Bean 實(shí)例,并從硬盤(pán)中將之前的狀態(tài)恢復(fù)。標(biāo)注了這個(gè)注釋的方法

53、會(huì)在激活完成時(shí)被調(diào)用。這個(gè)注釋只適用于有狀態(tài)會(huì)話(huà)bean。 Init:這個(gè)注釋指定了有狀態(tài)bean 初始化的方法。它區(qū)別于PostConstruct 注釋在于:多個(gè)Init 注釋方法可以同時(shí)存在于有狀態(tài)session bean 中,但每個(gè)bean 實(shí)例只會(huì)有一個(gè)Init 注釋的方法會(huì)被調(diào)用。PostConstruct 在Init 之后被調(diào)用。 Remove:當(dāng)客戶(hù)端調(diào)用標(biāo)注了Remove 注釋的方法時(shí),容器將在方法執(zhí)行結(jié)束后把bean 實(shí)例刪除。,個(gè)回調(diào)方法,要處理這些生命周期事件,我們可以為這些事件注冊(cè)一個(gè)回調(diào)方法,回調(diào)方法可以使用任何名稱(chēng),但是它必須返回void,不帶參數(shù),且不能拋出任何c

54、hecked exception。事件注冊(cè)的過(guò)程很簡(jiǎn)單,只需在回調(diào)方法上面加上事件的注釋就可以。,LifeCycleBean.java,Stateful Remote (LifeCycle.class) public class LifeCycleBean implements LifeCycle public String Say() try Thread.sleep(1000*10); catch (InterruptedException e) e.printStackTrace(); return 這是會(huì)話(huà)Bean生命周期應(yīng)用例子; Init public void initializ

55、e () System.out.println(Init事件觸發(fā)); ,攔截器(Interceptor),攔截器可以攔截Session bean 和message-driven bean 的方法調(diào)用或生命周期事件。攔截器用于封裝應(yīng)用的公用行為,使這些行為與業(yè)務(wù)邏輯分離,一旦這些公用行為發(fā)生改變,而不必修改很多業(yè)務(wù)類(lèi)。攔截器可以是同一bean類(lèi)中的方法或是一個(gè)外部類(lèi)。,外部攔截器類(lèi),Stateless Remote (HelloChinaRemote.class) Local(HelloChina.class) Interceptors(HelloInterceptor.class) publi

56、c class HelloChinaBean implements HelloChina,HelloChinaRemote public String SayHello(String name) return name +說(shuō):你好!中國(guó).; public String Myname() return 我是佛山人; ,Interceptors 注釋指定一個(gè)或多個(gè)在外部類(lèi)中定義的攔截器,多個(gè)攔截器類(lèi)之間用逗號(hào)分隔,上面攔截器HelloInterceptor 對(duì)HelloChinaBean 的所有方法進(jìn)行攔截。如果你只需對(duì)某一方法進(jìn)行攔截,你可以在方法上面定義攔截器。,攔截器HelloInterce

57、ptor.java,public class HelloInterceptor AroundInvoke public Object log(InvocationContext ctx) throws Exception System.out.println(* HelloInterceptor intercepting); long start = System.currentTimeMillis(); try if (ctx.getMethod().getName().equals(SayHello) System.out.println(* SayHello 已經(jīng)被調(diào)用! * ); if

58、 (ctx.getMethod().getName().equals(Myname) System.out.println(* Myname 已經(jīng)被調(diào)用! * ); return ceed(); catch (Exception e) throw e; finally long time = System.currentTimeMillis() - start; System.out.println(用時(shí):+ time + ms); ,InvocationContext 的定義,package erceptor; public interface InvocationContext public Object getTarget( ); public Me

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論