EJB 2.0:“本地”接口和“遠(yuǎn)程”接口
個(gè)新的接口可以使你更有效地訪問EJB。學(xué)習(xí)如何運(yùn)用它們,以及何時(shí)運(yùn)用它們。by Rudy Dahbura
當(dāng)前的EJB 2.0規(guī)范有新的接口功能,這在原先的EJB 1.1中是沒有的。學(xué)習(xí)運(yùn)用這些新的功能,它們可以使你更容易地、更有效地訪問EJB。
缺點(diǎn)是什么呢?你將犧牲位置的獨(dú)立性,但有時(shí)侯,這種代價(jià)是值得的。了解何時(shí)、如何運(yùn)用新的功能對編寫設(shè)計(jì)良好的EJB應(yīng)用程序是至關(guān)重要的。
EJB 1.1規(guī)范給EJB客戶端提供了一個(gè)remote interface和一個(gè)remote home interface與EJB實(shí)例交互,得到位置的透明度。以類似的形式,EJB 2.0規(guī)范現(xiàn)在給EJB客戶端提供了一個(gè)local interface和一個(gè)local home interface來與共享同一個(gè)JVM的EJB實(shí)例交互。
EJB remote interface(javax.ejb.EJBObject)和remote home interface(javax.ejb.EJBHome)在本質(zhì)上是Java RMI接口。遠(yuǎn)程客戶端運(yùn)用接口和與Java RMI-IIOP兼容的參數(shù)與EJBs通訊。參數(shù)和方法的結(jié)果值在同一個(gè)容器中傳遞,或者跨網(wǎng)絡(luò)傳遞到遠(yuǎn)程容器。
這種編程模式給EJB客戶端提供了一種訪問EJB組件的方法,就好像這些組件是本地的一樣。然后,容器就可以透明地處理網(wǎng)絡(luò)通訊和執(zhí)行其它功能。這種方法很適合粗粒度的(coarse-grained)方法調(diào)用,其中客戶端和EJBs之間的客戶端通訊保持到最小限度。
相反,EJB local interface(javax.ejb.EJBLocalObject)和local home interface(javax.ejb.EJBLocalHome)不是Java RMI接口,它們是EJB 2.0的新功能。本地客戶端——如其它EJBs,運(yùn)用相同JVM中傳遞的參數(shù)直接與EJBs通訊。這種技術(shù)消除了網(wǎng)絡(luò)潛在的問題、參數(shù)復(fù)制的問題以及需要與Java RMI-IIOP兼容的問題。也意味著,EJB客戶端可以運(yùn)用一個(gè)更輕量級(jí)的編程模式來訪問服務(wù)。該方法很適合細(xì)粒度的(fine-grained)方法調(diào)用,因?yàn)樽鳛镋JB實(shí)例的位于同一個(gè)JVM中的EJB客戶端可以用本地接口來避免不必要的費(fèi)用。
引進(jìn)本地客戶端產(chǎn)生的另一個(gè)顯著的變化就是類型的轉(zhuǎn)換。所有的EJB實(shí)例在運(yùn)用前必須轉(zhuǎn)換到它們恰當(dāng)?shù)慕涌陬愋停裕袝r(shí)侯,在運(yùn)用遠(yuǎn)程客戶端時(shí),要保證Java RMI-IIOP的兼容性,你必須在轉(zhuǎn)換EJB實(shí)例前運(yùn)用java.rmi.PortableRemoteObject.narrow()來縮小(narrow)它。
但本地客戶端可以直接把EJB實(shí)例轉(zhuǎn)換成local home interface類型,如下面的代碼片段:
InitialContext initCtx = new
InitialContext();
ExampleLocalHome exampleLocalHome =
(ExampleLocalHome)initCtx.lookup("java:comp/
env/ejb/Example");
從local home創(chuàng)建了EJB實(shí)例:
ExampleLocal exampleLocal =
exampleLocalHome.create();
也許EJB 2.0的最有趣、最容易被忽視的一個(gè)方面就是session和entity beans可以同時(shí)運(yùn)用遠(yuǎn)程和本地接口,這就給了你很大的靈活性。運(yùn)用兩種接口給了潛在的bean客戶端最大程度的自由,不管它們是不是在一起的。
<session>和<entity>元素描述了session和entity bean的部署屬性。EJB 1.1和EJB 2.0規(guī)范定義了兩個(gè)元素,<home>和<remote>。(以前的規(guī)范需要兩個(gè)元素,但它們在2.0版中是可選的)。它們分別包含EJB remote home interface和remote interface的完全資格類名。
類似地,EJB 2.0規(guī)范定義了兩個(gè)附加的元素,<local-home>和<local>。正如你預(yù)料的,它們包含EJB local home interface和local interface的完全資格類名。下面的代碼顯示了如何運(yùn)用這些新元素:
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>...</ejb-name>
<local-home>...</local-home>
<local>...</local>
<ejb-link>...</ejb-link>
...
</session>
</enterprise-beans>
<assembly-descriptor>
...
</assembly-descriptor>
</ejb-jar>
聰明地訪問本地客戶端的一個(gè)實(shí)例
本地EJB客戶端的概念在如列表1所示的例子中得到了很好地闡明,其中顯示了一個(gè)無狀態(tài)session bean,它的local interface和它的local home interface。注意,接口不擴(kuò)展java.rmi.Remote。
無狀態(tài)session bean的XML部署描述如下面的代碼所示,它也重點(diǎn)強(qiáng)調(diào)了<local>和<local-home>元素的運(yùn)用:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC
'-//Sun Microsystems, Inc.//DTD Enterprise
JavaBeans 2.0//EN'
'http://java.sun.com/dtd/ejb-jar_2_0.dtd'>
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>Example</ejb-name>
<local-
home>com.acmecorp.ejb.ExampleLocalHome</
local-home>
<local>com.acmecorp.ejb.ExampleLocal</local>
<ejb-
class>com.acmecorp.ejb.ExampleBean</
ejb-class>
<session-
type>Stateless</session-type>
<transaction-
type>Container</transaction-type>
</session>
</enterprise-beans>
<assembly-descriptor>
<method-permission>
<unchecked/>
<method>
<ejb-name>Example</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<container-transaction>
<method>
<ejb-name>Example</ejb-name>
<method-name>*</method-name>
</method>
<trans-
attribute>NotSupported</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>
然后,一個(gè)本地的客戶端創(chuàng)建并訪問一個(gè)已經(jīng)創(chuàng)建的enterprise bean的實(shí)例。下面的代碼也顯示了如何轉(zhuǎn)換一個(gè)bean的實(shí)例,而不用先縮小它:
<%@ page errorPage="/error.jsp"
import="javax.naming.*,
com.acmecorp.ejb.*"
%>
<%
InitialContext initCtx = new InitialContext();
ExampleLocalHome exampleLocalHome =
(ExampleLocalHome)initCtx.lookup("java:comp/env/
ejb/Example");
ExampleLocal exampleLocal =
exampleLocalHome.create();
%>
<html>
<head>
<title>Default</title>
<link rel="STYLESHEET" type="text/css"
href="styles/default.css">
</head>
<body>
<pre class="code"><%=
exampleLocal.getMessage() %></pre>
</body>
</html>
在這個(gè)例子中,本地客戶端是一個(gè)JSP頁面,因此是一個(gè)Web組件。(在有些情況中,當(dāng)Web組件位于相同的JVM中時(shí),它們訪問EJB 2.0本地組件接口。)
最后是Web組件的部署描述:
<web-app>
<!-- EJB Reference information -->
<ejb-local-ref>
<ejb-ref-name>ejb/Example<
/ejb-ref-name>
<ejb-ref-type>Session<
/ejb-ref-type>
<local-home>com.acmecorp.ejb.ExampleLocalHome<
/local-home>
<local>com.acmecorp.ejb.ExampleLocal<
/local>
<ejb-link>Example</ejb-link>
</ejb-local-ref>
</web-app>
注意用<ejb-local-ref>元素來聲明本地EJB引用。通過<ejb-link>元素得到一個(gè)明顯的與EJB的鏈接。它的值必須等于EJB XML描述符中的<ejb-name>元素。
未來會(huì)有更大的靈活性?
目前還是公開草案的EJB 2.1規(guī)范為訪問無狀態(tài)session beans定義了一個(gè)Web services客戶端。遠(yuǎn)程客戶端將以一種位置獨(dú)立的方式與無狀態(tài)session beans通訊,這種通訊主要運(yùn)用SOAP 1.1通過HTTP進(jìn)行基于XML的調(diào)用。因?yàn)閄ML、SOAP和HTTP是獨(dú)立于語言的,所以客戶端不需要是Java對象,可以是運(yùn)行在不同平臺(tái)上的其它類型的對象。
到那時(shí),EJB 2.0的新功能就會(huì)更受Java開發(fā)人員的歡迎了,使他們能夠創(chuàng)建代碼,更有效地運(yùn)用本地和遠(yuǎn)程接口。通過運(yùn)用這些功能,并對你的設(shè)計(jì)能力進(jìn)行正確的評(píng)估,你就可以創(chuàng)建應(yīng)用程序,使它們最大限度地運(yùn)用EJBs。
關(guān)于作者:
Rudy Dahbura是位住在洛杉磯的軟件顧問。他在洛杉磯的Sierra Systems Group工作,他運(yùn)用分布式對象技術(shù)已經(jīng)有五年了。他的聯(lián)系方式是rdahbura@sierrasystems.com。
posted on 2005-12-02 17:03 輕松 閱讀(4408) 評(píng)論(2) 編輯 收藏 所屬分類: JAVA轉(zhuǎn)貼