開發(fā)具有本地接口的無狀態(tài)session bean
當(dāng)通過遠(yuǎn)程接口調(diào)用EJB時(shí):
首先客戶端需要與ejb建立起socket通信,在通信管道上他們之間需要來回發(fā)送IIOP協(xié)議消息,因?yàn)閿?shù)據(jù)要在網(wǎng)絡(luò)進(jìn)行傳輸,存放數(shù)據(jù)的java對象必須要進(jìn)行序列化bean" name="image_operate_51381323502849734" alt="開發(fā)具有本地接口的無狀態(tài)session
在這個(gè)過程中,有網(wǎng)絡(luò)通信的開銷、協(xié)議解析的開銷、對象序列化的開銷。因?yàn)?font color="#f70e02">ejb是分布式技術(shù),它允許客戶端與ejb應(yīng)用在不同一機(jī)器上面,所以這些性能開銷也是必然的。
但是在實(shí)際生產(chǎn)中,不可避免這種情況:客戶端與EJB應(yīng)用運(yùn)行在同一臺(tái)機(jī)器上的同一個(gè)jboss中。
那么這個(gè)時(shí)候客戶端是否還有必要跟ejb之間走上面的網(wǎng)絡(luò)通信呢?
這個(gè)時(shí)候的客戶端與ejb是在同一個(gè)jvm內(nèi),他們之間完全可以通過內(nèi)存進(jìn)行交互,如果如此,完全可以避免上面流程的性能開銷,所以引入了——本地接口
通過本地接口調(diào)用ejb,直接在內(nèi)存交互,這樣可以避免因網(wǎng)絡(luò)通信所造成的各種性能開銷,但有一點(diǎn)需要注意:
只有客戶端與EJB應(yīng)用都在同一個(gè)JVM內(nèi)運(yùn)行的時(shí)候,才能調(diào)用本地接口,否則只能調(diào)用遠(yuǎn)程接口。
什么情況下客戶端與EJB應(yīng)用是在同一個(gè)JVM?
只要客戶端與EJB發(fā)布在同一個(gè)jboss內(nèi),就可以認(rèn)為他們在同一個(gè)JVM
---------------------------------------------------------------
在原有的HelloWorld項(xiàng)目中,修改HelloWorldBean.java
將@Remote(HelloWorld.class)
修改為@Local(HelloWorld.class) 就可完成本地接口
具有本地接口的無狀態(tài)bean已經(jīng)被開發(fā)
運(yùn)行ANT的deploy將EJB部署到j(luò)boss中,通過控制臺(tái)可以看到ejb已經(jīng)成功部署
當(dāng)EJB部署成功,jboss會(huì)為這個(gè)本地接口,生成出一個(gè)JNDI名稱
開發(fā)EJB的客戶端 http://blog.sina.com.cn/s/blog_8020e411010123yl.html博文中講述了
jboss生成JNDI默認(rèn)命名規(guī)則,這里不再贅述
這里生成的JNDI名稱為:HelloWorldBean/local
在客戶端,通過該JNDI名稱,使用本地接口,訪問EJB
此時(shí)會(huì)報(bào)錯(cuò),原因是客戶端和EJB不在同一個(gè)JVM內(nèi)
新建一個(gè)web項(xiàng)目,將其部署在jboss下,使客戶端與EJB在同一個(gè)jboss中,方可使用本地接口
新建一個(gè)Test.jsp,將原EJBClient客戶端代碼,復(fù)制進(jìn)來
并講類引入進(jìn)來(<%@ page import="java.naming.*"%>)
此時(shí) HelloWorld helloWorld =
(HelloWorld)cts.lookup("HelloWorldBean/local");的HelloWorld類不存在,由于不是同一個(gè)項(xiàng)目,所以需要將剛才的EJBClient的java Project導(dǎo)入進(jìn)這個(gè)Web Project中
選中這個(gè)EJBClient的Web項(xiàng)目,右鍵,Properties
選擇剛才的EJB java Project,點(diǎn)OK
在Test.jsp頁面,完整的導(dǎo)入:
<%@ page import="javax.naming.*,com.test.ejb3.HelloWorld"
%>
<body>
InitialContext();
helloWorld =
(HelloWorld)cts.lookup("HelloWorldBean/local");
//$Proxy3
//hello說:你好,世界!
e){
%>
此時(shí)客戶端應(yīng)用已經(jīng)開發(fā)完成,然后導(dǎo)出war文件
將war文件,拷貝到j(luò)boss的發(fā)布目錄下進(jìn)行發(fā)布
如果:
InitialContext cts = new InitialContext();
為Application Server指定了JNDI名稱,那此程序只能運(yùn)行在這個(gè)Application Server中
如不寫參數(shù),則其構(gòu)造函數(shù)自動(dòng)尋找jndi的上下文信息,自動(dòng)與其綁定
要注意:在EJBClient的Web項(xiàng)目下,引用的HelloWorld接口,并沒有將它的class文件放入該web項(xiàng)目的classpath下
原因是:當(dāng)加載到HelloWorld類時(shí),沒有找到它時(shí),由于引用了HelloWorld
JavaProject項(xiàng)目,EJB類加載器就會(huì)去它的classpath中尋找
所以,當(dāng)WEB應(yīng)用和EJB應(yīng)用部署在同一個(gè)JVM內(nèi)時(shí),并不需要在客戶端應(yīng)用里面,放入EJB的接口類
如果將EJB接口類放入進(jìn)客戶端classpath中,有時(shí)會(huì)導(dǎo)致類型出圖問題
企業(yè)中,很有可能客戶端和EJB是部署在同一個(gè)JBOSS中,也可能部署在不同機(jī)器上
考慮到這兩點(diǎn),就會(huì)選用遠(yuǎn)程接口或本地接口
返回到剛才的HelloWorld java Project程序:
新建一個(gè)接口:
//繼承HelloWorld的業(yè)務(wù)方法
public interface HelloWorldLocal extends
HelloWorld{
}
修改實(shí)現(xiàn)的bean:
優(yōu)先調(diào)用本地接口
這樣就可以使:當(dāng)客戶端與EJB在同一個(gè)JBOSS中,使用本地接口
客戶端與EJB不在同一個(gè)JBOSS中,則使用遠(yuǎn)程接口
------------------------------------------------------------------
try{
InitialContext();
(HelloWorld)cts.lookup("HelloWorldBean/remote");//使用遠(yuǎn)程接口
//$Proxy3
//明明說:你好,世界!
e){
EJB與客戶端在同一個(gè)jboss中,也可用遠(yuǎn)程接口訪問
------------------------------------------------------------------
<body>
InitialContext();
(HelloWorldLocal)cts.lookup("HelloWorldBean/local"); //使用本地接口
//$Proxy3
//本地人說:你好,世界!
e){
%>
在Web客戶端與EJB使用同一個(gè)jboss,可用本地接口