ejb三種bean之會話bean

會話bean(session bean),可以分爲無狀態會話bean和有狀態會話bean

  負責與客戶端交互,是編寫業務邏輯的地方,在會話bean中可以通過jdbc直接操作數據庫,但大多數情況下都是通過實體bean來完成對數據庫的操作.

•無狀態會話bean

 平常,我們使用最多的是無狀態bean,因爲它的bean實例可供多個用戶使用,所以它的性能比有狀態bean高.正因爲一個bean實例被多個用戶使用.那麼,前一個用戶設置的值有可能被後一個用戶所修改,所以它無法正確保存某個用戶設置的值,因此是無狀態的.

•有狀態會話bean

有狀態bean平常使用的並不多,因爲它的一個bean實例只供一個用戶使用,所以性能開銷比較大,正因爲它的實例只被一個用戶使用,用戶爲它設置的值是不會被其他用戶修改,所以可以正確保存用戶設置的值,因此是有狀態的.

如何開發一個無狀態會話bean?

 1.可以在jboss安裝路徑的client目錄下找到,通常會把client目錄下的所有jar文件添加到項目的類路徑下.

2.開發接口和實現類:

•接口(接口可以是遠程接口或本地接口)
public interface HelloWorld {
public String sayHello(String name);
}
•實現類
@Stateless
@Remote(HelloWorld.class)

public class HelloWorldBean implements HelloWorld {
@Override
public String sayHello(String name) {
return name+"說:你好啊!";
}
}
把以上打包成jar,然後將打好的jar放到default這個配置項的deploy目錄下面,就將這個ejb發佈了.jboss就可以自動對它進行部署了
ejb在軟件開發的分層中它屬於業務層,通常它是需要被客戶端進行調用的.MVC中想想,這個客戶端可以是jse,jme等.

會話bean的客戶端:

public class EJBClient {
public static void main(String[] args) {
try {
InitialContext ctx = new InitialContext();
HelloWorld helloworld = (HelloWorld) ctx
.lookup("HelloWorldBean/remote");//參數裏面的是JNDI名稱
System.out.println(helloworld.sayHello("張三"));
} catch (NamingException e) {
System.out.println(e.getMessage());
}
}
}

重要的幾點:

1.在進行JNDI查找前,我們必須設置應用服務器的上下文信息,主要是設置JNDI驅動的類名(java.naming.factory.initial)和命名服務提供者的URL (java.naming.provider.url) 。

如同數據庫一樣,根據訪問命名服務器的不同,爲上下文設置的驅動類和URL也是不同的

創建InitialContext對象時如果沒有指定Properties參數,InitialContext還會在classpath下尋找jndi.properties文件,並從該文件中加載應用服務器的上下文信息。這樣避免了硬編碼爲InitialContext設置Properties參數。

jndi.properties的配置如下:(這個是用作爲jboss應用服務器的上下文信息)

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory

java.naming.provider.url=localhost:1099

java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

2.

當EJB發佈到Jboss 時,如果我們沒有爲它指定全局JNDI名稱或修改過其默認EJB名稱,Jboss就會按照默認的命名規則爲EJB生成全局JNDI名稱,默認的命名規則如下:

如果把EJB作爲模塊打包進後綴爲*.ear的JAVA EE企業應用文件,默認的全局JNDI名稱是

l本地接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/local
l遠程接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/remote

      EAR-FILE-BASE-NAME爲ear文件的名稱,EJB-CLASS-NAME爲EJB的非限定類名。

例:把HelloWorld應用作爲EJB模塊打包進名爲HelloWorld.ear的企業應用文件,它的遠程接口的JNDI 名稱是:HelloWorld/HelloWorldBean/remote

如果把EJB應用打包成後綴爲*.jar的模塊文件,默認的全局JNDI名稱是

l本地接口:EJB-CLASS-NAME/local
l遠程接口:EJB-CLASS-NAME/remote

例:把HelloWorld應用打包成HelloWorld.jar文件,它的遠程接口的JNDI名稱是:HelloWorldBean/remote

可以使用註釋改變會話Bean的JNDI 名稱

如果我們沒有指定EJB的JNDI名稱,當EJB發佈到應用服務器時,應用服務器會按默認規則爲EJB生成全局JNDI名稱。當我們需要自定義JNDI名稱時,可以這樣做

如果EJB在Jboss中使用,可以使用Jboss提供的 @LocalBinding 和 @RemoteBinding 註釋,@LocalBinding註釋指定Session Bean的Local接口的JNDI名稱,@RemoteBinding註釋指定Session Bean的Remote接口的JNDI名稱,如下:

@Stateless

@Remote ({Operation.class})

@RemoteBinding (jndiBinding="foshanshop/RemoteOperation")

@Local ({LocalOperation.class})

@LocalBinding (jndiBinding="foshanshop/LocalOperation")

public class OperationBean implements Operation, LocalOperation {

}

也可以使用xml部署描述文件改變SessionBean的JNDI 名稱

由於JNDI名稱與廠商有關,如果使用註釋定義JNDI名稱會帶來移植問題,因此建議使用ejb-jar.xml部署描述文件進行定義,該文件必須放置在jar的META-INF目錄下

<?xml version="1.0"encoding="UTF-8"?>

<ejb-jar  xmlns=http://java.sun.com/xml/ns/javaee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

                         http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"  version="3.0">

<enterprise-beans>

 <session>

   <ejb-name>HelloWorldBean</ejb-name>

   <mapped-name>HelloWorldBean</mapped-name>

 </session>

</enterprise-beans>

</ejb-jar>

ejb-name爲EJB名稱,mapped-name爲bean的JNDI名稱。目前jboss不支持在ejb-jar.xml通過mapped-name指定JNDI名稱,但我們可以使用他專屬的部署描述文件jboss.xml進行定義,如下:

<?xml version="1.0"encoding="UTF-8" ?>

<!DOCTYPE jboss PUBLIC "-//JBoss//DTDJBOSS 4.2//EN“ "http://www.jboss.org/j2ee/dtd/jboss_4_2.dtd">

<jboss><enterprise-beans> <session>

     <ejb-name>HelloWorldBean</ejb-name>

    <jndi-name>hello/remote</jndi-name>

</session></enterprise-beans></jboss>

具有Local接口的Session bean

首先了解一下通過遠程接口調用ejb的過程,首先客戶端需要與ejb建立起socket通信,在通信管道上他們之間需要來回發送IIOP協議消息,因爲數據要在網絡進行傳輸,存放數據的java對象必須要進行序列化。


在這個過程中我們看到,有網絡通信的開銷、協議解析的開銷、對象序列化的開銷。因爲ejb是分佈式技術,它允許客戶端與ejb應用在不同一機器上面,所以這些性能開銷也是必然的。但是在實際生產中,不可避免存在這種情況:客戶端與EJB應用運行在同一個jboss中。這時候客戶端訪問ejb是否有必要走上面的網絡通信呢?據我們所知,這時候客戶端與ejb是在同一個jvm內,他們之間完全可以通過內存進行交互,這樣就可以避免網絡通信的性能開銷。既然我們都想到了這一點,EJB專家組也想到了這一點,所以引入了本地接口。通過本地接口調用ejb,直接在內存中交互,這樣就能避免因網絡通信所造成的各種性能開銷。但是有一點,大家必須注意,只有客戶端與EJB應用在同一個JVM內運行的時候,我們才能調用本地接口,否則只能調用遠程接口。談到這裏,有同學會問什麼情況下客戶端與EJB應用是在同一個JVM?簡單地說只要客戶端與ejb發佈在同一個jboss內,我們就認爲他們是在同一個JVM

@Stateless

@Local ({HelloWorldLocal.class})

public class HelloWorldBean implements HelloWorldLocal {

   public String say (String name) {       

        return name +"說:你好!世界,這是我的第一個EJB3哦.";

   }

}

如何訪問具有本地接口的會話bean呢?

新建一個web項目,在jsp裏面進行訪問 ,然後打好war包,把打好的war包放到jboss的default/deploy目錄下面,這樣確保客戶端與EJB應用運行在同一個jboss中

<%@ page import="cn.itcast.ejb3.HelloWorldLocal, javax.naming.*, java.util.Properties"%>

<%

try {

  InitialContext ctx = new InitialContext();

  HelloWorldLocal helloworld = (HelloWorldLocal) ctx.lookup("HelloWorldBean/local");

  out.println(helloworld.sayHello("佛山人"));

} catch (NamingException e) {

  out.println(e.getMessage());

}

%>

然後訪問這個jsp頁面即可

一般做應用的時候是既做一個本地接口,也做一個遠程接口如果客戶端應用與ejb部署在同一個jboss內的話,會優先應用本地接口,否則用遠程接口.



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章