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

下載本文檔

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

文檔簡介

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

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

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

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

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

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

7、擊下載。(注:本書光盤“軟件”文件夾中帶有JDK 5.0) 按照安裝向?qū)崾景惭b,安裝路徑選擇C:Javajdk1.5.0_14。Jdk 安裝完后,接著問你是否安裝jre,也一起安裝上。 右鍵點擊“我的電腦”-“屬性”-“高級”-“環(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 的選項,點“編輯”在變量值的末尾添加;%JAVA_HOM

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

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

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

11、上輸入:http:/localhost:8080/EJBTest/Test.jsp(注意大小寫)。將會看見下圖所示。,運行第一個EJB3 例子,在JBoss 部署應(yīng)用,在JBoss 部署應(yīng)用的過程非常簡單、直接。在每一個配置中,Jboss 會不斷掃描一個名為jboss 安裝目錄/server/config-name/deploy 的特定目錄,查看是否有任何更新,此目錄一般被稱為“部署目錄”。 你可以把下列文件拷貝到部署目錄中: 任何Java 庫(其中的類將被自動添加到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 將通過對比時間戳來檢測變化,卸載舊文件,部署相應(yīng)的新文件。如果要重新部署目錄,只需更新其時間戳即可。從部署目錄中刪除文件會導(dǎo)致相應(yīng)文件從部署中卸載。,會話Bean(Session Bean),Session Bean 是實現(xiàn)業(yè)務(wù)邏輯的地方。簡單地說,像我們要實現(xiàn)兩數(shù)相加或是從數(shù)據(jù)庫

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

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

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

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

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

18、va 。Bean 類推薦的命名方式是:接口+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 +說:你好!世界,這是我的第一個EJB3哦.; ,Stateless 注釋,在Bean 類上面有兩個注釋Stateless 和Remote,Stateless 注釋指明這是一個無狀態(tài)會話Bean。Stateless 注釋的定義如下: Package javax.ejb; Target(TYPE) Retention(RUNTIME) public interface Stateless String name( ) default ; String mappedName() default ; name()屬性用于指定session bean 的EJB 名稱。該名稱在EJB J

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

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

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

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

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

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

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

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

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

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

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

31、Context 對象時如果沒有指定Properties 參數(shù),InitialContext 內(nèi)部會調(diào)用System.getProperty()方法從系統(tǒng)屬性里獲取必要的上下文信息。對本例子而言,你可以省略傳入props 參數(shù)。在實際應(yīng)用中,如果給InitialContext 設(shè)置了參數(shù),反而會帶來不可移植的問題。,上下文環(huán)境,創(chuàng)建InitialContext 對象時如果沒有指定Properties 參數(shù),InitialContext 還會在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 名稱通過lookup()方法查找EJB。lookup()方法返回一個存根對象,該存根實現(xiàn)了HelloWorld

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

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

35、ean 類: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 +說:你好!世界,這是一個只具有Local接口的無狀態(tài)Bean; ,客戶端代碼,把上面的EJB 打成jar 文件后,發(fā)布到j(luò)boss 安裝目錄serverdefaultdeploy 目錄中。接下來我們編寫客戶端調(diào)用代碼。 LocalSessionBeanTest.jsp ,開發(fā)實現(xiàn)了Remote 與Local 接口的無狀態(tài)Session Bean,在實際應(yīng)用中,同時實現(xiàn)Remote 與Local 接口是一種比較好的做法。這樣你既可以在遠程訪問EJB,也可以在本地訪問EJB。 遠程接口:Operation.java package com.foshanshop.ejb3; pu

37、blic interface Operation public int Addup(); 本地接口:LocalOperation.java,本地接口繼承了遠程接口的所有方法 package com.foshanshop.ejb3; public interface LocalOperation extends Operation ,會話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 客戶端:OperationBeanT

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

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

41、n(有狀態(tài)bean)開發(fā),stateless session bean 創(chuàng)建在對象池中,提供給眾多用戶使用,如果Bean class 有自己的成員屬性(變量),那么這些變量就會受到所有調(diào)用它的用戶影響。在一些應(yīng)用場合中,有時我們需要每個用戶都有自己的一個實例,這個實例不受其他用戶影響。就好比購物車對象,每個用戶都應(yīng)有自己的購物車,你不希望有人往你的購物車里添加或拿掉商品,而有狀態(tài)Bean 正好滿足你的這種需求。每個有狀態(tài)Bean 在bean 實例的生命周期內(nèi)都只服務(wù)于一個用戶,bean class 的成員變量可以在不同的方法調(diào)用間維護特定于某個用戶的數(shù)據(jù)。正因為在bean 實例的生命周期內(nèi),S

42、tateful Session Bean 保持了用戶的信息,所以叫有狀態(tài)Bean。,Stateful Session Bean(有狀態(tài)bean)開發(fā),stateless session bean 創(chuàng)建在對象池中,提供給眾多用戶使用,如果Bean class 有自己的成員屬性(變量),那么這些變量就會受到所有調(diào)用它的用戶影響。在一些應(yīng)用場合中,有時我們需要每個用戶都有自己的一個實例,這個實例不受其他用戶影響。就好比購物車對象,每個用戶都應(yīng)有自己的購物車,你不希望有人往你的購物車里添加或拿掉商品,而有狀態(tài)Bean 正好滿足你的這種需求。每個有狀態(tài)Bean 在bean 實例的生命周期內(nèi)都只服務(wù)于一個

43、用戶,bean class 的成員變量可以在不同的方法調(diào)用間維護特定于某個用戶的數(shù)據(jù)。正因為在bean 實例的生命周期內(nèi),Stateful Session Bean 保持了用戶的信息,所以叫有狀態(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 類: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 注釋指明這是一個有狀態(tài)會話Be

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

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

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

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

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

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

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

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

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

54、hecked exception。事件注冊的過程很簡單,只需在回調(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 這是會話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ù)類。攔截器可以是同一bean類中的方法或是一個外部類。,外部攔截器類,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 +說:你好!中國.; public String Myname() return 我是佛山人; ,Interceptors 注釋指定一個或多個在外部類中定義的攔截器,多個攔截器類之間用逗號分隔,上面攔截器HelloInterceptor 對HelloChinaBean 的所有方法進行攔截。如果你只需對某一方法進行攔截,你可以在方法上面定義攔截器。,攔截器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(用時:+ time + ms); ,InvocationContext 的定義,package erceptor; public interface InvocationContext public Object getTarget( ); public Me

溫馨提示

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

評論

0/150

提交評論