程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 循速漸進學用Session Bean(三)

循速漸進學用Session Bean(三)

編輯:關於JAVA

創建無狀態的Session Bean

從編程的角度看,創建無狀態的Session Bean和創建有狀態的是一樣簡單的。除了在配置工具裡修改一個設置外,僅有的一點不同是在bean的初始設計階段,無狀態的Session Bean並不記得方法調用之間的任何東西,bean需要的任何消息都必須由客戶端獲得。雖然無狀態的Session Bean並不記得面向session的數據,不過可以在一個無狀態的session bean中存放數據,只是不能存放與客戶端相關的數據。

在HelloWorldSession的例子中,該bean在方法調用之間仍記得一個問候的字符串。例如,你調用setGreeting來修改歡迎詞,當你調用getGreeting時,該session會記得保存的歡迎詞。

列表6.5“Hello World”session bean Remote 接口(無狀態版本)

  Listing 6.5 Source Code for StatelessHello.java
package usingj2ee.hello;
  import java.rmi.*;
import javax.ejb.*;
  /** Defines the methods you can call on a StatelessHello object */
  public interface StatelessHello extends EJBObject
{
  /** Returns a greeting for the named object */
public String greet(String thingToGreet) throws RemoteException;
  }

在這個例子中,Remote接口僅提供了一個greet方法,該方法接收一個參數並且返回一個歡迎詞。例如,如果傳送“World”參數給greet,greet方法將返回“Hello World!”。

列表6.6展示了StatelessHello bean的Home接口。

  Listing 6.6 Source Code for StatelessHelloHome.java
package usingj2ee.hello;
  import java.rmi.*;
import javax.ejb.*;
  /** Defines the methods for creating a StatelessHelloWorld */
  public interface StatelessHelloHome extends EJBHome
{
  /** Creates a StatelessHello session bean. A stateless session bean
can't have a create method that takes parameters. */
public StatelessHello create() throws RemoteException, CreateException;
  }

無狀態的session bean僅擁有一個create方法,而且該方法不能接受任何參數。這看起來有些奇怪,不過如果考慮到無狀態session bean的含義你就會明白了。這種bean不能記住某個客戶的任何信息,實際上,為了性能上的原因,容器也許會不時地讓不同的session處理某個客戶的方法調用。由於session並不需要記住某個客戶的信息,因此使用另一個bean來處理負載並不會帶來任何問題。

如果bean的create方法接受任何的參數,session bean實例之間的行為將會有所不同,因為你為create方法提供不同的值。

實現無狀態session bean與有狀態的session bean是一樣簡單的。列表7中的是StatelessHelloImpl類,它實現了Remote和Home接口。

  Listing 6.7 Source Code for StatelessHelloImpl.java
package usingj2ee.hello;
  import java.rmi.*;
import java.util.*;
import javax.ejb.*;
  /** The implementation class for the StatelessHello bean */
  public class StatelessHelloImpl implements SessionBean
{
/** The session context provided by the EJB container. A session bean must
hold on to the context it is given. */
private SessionContext context;
  /** An EJB must have a public, parameterless constructor */
  public StatelessHelloImpl()
{
}
  /** Called by the EJB container to set this session's context */
  public void setSessionContext(SessionContext aContext)
{
context = aContext;
}
  /** Called by the EJB container when a client calls the create() method in
the Home interface */
public void ejbCreate()
throws CreateException
{
}
  /** Called by the EJB container to wake this session bean up after it
has been put to sleep with the ejbPassivate method. */
  public void ejbActivate()
{
}
  /** Called by the EJB container to tell this session bean that it is being
suspended from use (it's being put to sleep). */
  public void ejbPassivate()
{
}
  /** Called by the EJB container to tell this session bean that it has been
removed, either because the client invoked the remove() method or the
container has timed the session out. */
  public void ejbRemove()
{
}
  /** Returns a greeting for the named object */
  public String greet(String thingToGreet)
{
return "Hello "+thingToGreet+"!";
}
}

注意:

配置無狀態session bean的過程和有狀態bean幾乎是一樣的。只要確認已經配置bean為無狀態的,可能需要在Stateless的選項旁打上一個勾或者確認去除Manages Conversational State旁的選項。

列表6.8展示的是一個客戶測試無狀態session bean的代碼

  Listing 6.8 Source Code for TestStatelessHello.java
package usingj2ee.hello;
  import java.util.*;
import javax.naming.*;
import javax.rmi.*;
public class TestStatelessHello
{
public static void main(String[] args)
{
try
{
  /** Creates a JNDI naming context for location objects */
Context context = new InitialContext();
  /** Asks the context to locate an object named "HelloWorld" and expects the
object to implement the HelloWorldSessionHome interface */
  StatelessHelloHome home = (StatelessHelloHome)
PortableRemoteObject.narrow(
context.lookup("StatelessHello"),
StatelessHelloHome.class);
/** Asks the Home interface to create a new session bean */
StatelessHello session = (StatelessHello) home.create();
  System.out.println(session.greet("World"));
System.out.println(session.greet("Solar System"));
System.out.println(session.greet("Universe"));
  /** Destroy this session */
session.remove();
}
catch (Exception exc)
{
exc.printStackTrace();
}
}
}

圖6.7展示了TestStatelessHello程序的輸出

******************圖6.7 *****************

Sessin Bean的更多細節問題

現在我們對session bean的結構及如何實現已經有了一個認識,為了在設計和開發session bean時更有效率,還需要知道一些更多的細節問題。

SessionBean的接口

每一個session bean都必須實現SessionBean接口,它包含有4個方法,EJB容器使用這些方法來管理session bean。

setSessionContext

SessionContext對象包含有session bean運行環境的信息,並包含到Home接口的引用,以及自身的引用,事務信息和某個方法調用者的標識符。

對於每個session bean,setSessionContext方法都會被調用一次,這也bean初始化的一部分。在調用setSessionContext後,該bean就成為EJB容器的一個活動部分,並且一直保持活動狀態,直到調用ejbRemove為止。

提示

setSessionContext方法是放入初始代碼的好地方,在這裡可以創建數據庫連接或者查找另一個bean的Home接口。

在setSessionContext接口的方法中,getEJBObject可能是最常調用的一個。有時EJB必須傳送自己到另一個方法中。例如,假定你擁有一個ShoppingCart bean,包含有顧客想要訂購的商品信息。此外,還擁有一個OrderPlacement session bean負責接收ShoppingCart的內容並將它輸入定單系統中。當公司希望將現有的定單系統移植到另一個平台上,例如由大型機轉移到EJB服務器時,只需要修改OrderPlacement bean而無需理會shopping cart。ShoppingCart bean管理用戶想要購買的東西,OrderPlacement bean負責放置定單。

現在,當ShoppingCart bean需要調用OrderPlacement bean時,它只是使用this關鍵字來傳送自己:

orderPlacementBean.submitOrder(this);

這裡的問題是submitOrder方法的聲明也許如下所示:

public void submitOrder(ShoppingCart cart) throws RemoteException;

這裡有一個問題,因為ShoppingCart是session bean的Remote接口(至少這個例子中是),this變量將指向一個ShoppingCartImpl對象,不過該對象並沒有實現ShoppingCart的接口。使用EJB時,這些區別將會令你感到迷惑。一個EJB實際上有兩部分:Remote接口和實現。實現並不是一個遠程的對象,也就是說,它並不實現Remote接口。實際上,在許多的EJB實現中,Remote接口調用容器上的方法,而容器就調用實現上的方法,就好象調用標准方法一樣,例如ejbCreate和ejbRemove。

調用submitOrder的正確方式是

orderPlacementBean.submitOrder((ShoppingCart) sessionContext.getEJBObject());

當然,對於這段代碼,它是假定setSessionContext方法是這樣的:

public void setSessionContext(SessionContext aContext)
{
sessionContext = aContext;
}

即使在你的bean中並不需要session context,保留它也是一個好主意。它僅需要幾行代碼,這樣就可以認為一直存在這個方法。

提示

如果讓保留session context成為一個標准,那麼還需要標准化對context的訪問。也就是說,為context選擇一個標准化的變量名字,或者創建一個標准的方法,例如getSessionContext。

ejbRemove

EJB容器調用session bean的ejbRemove方法來告訴該bean的服務將要停止。這時bean應該要清除它保留的全部資源。

提示

如果bean在setSessionContext方法中建立了一個數據庫連接,那麼需要在ejbRemove方法中關閉該連接。如果你創建了任何的session bean,也可在ejbRemove方法中移除,同時將定位的Home接口設置為null。

ejbPassivate 和 ejbActivate

Enterprise JavaBeans規范中,提供了各種方法讓EJB容器實現負載均衡以及其它各種和性能相關的工作。Passivation/Activation就是這樣一個操作,它與計算機管理內存的方式是類似的。

ejbPassivate 和 ejbActivate 方法允許一個EJB容器來使用內存交換技術。在某個時刻,如果EJB容器覺得內存中的許多bean都有一段時間沒人訪問了,它可能選擇將其中的bean存儲到磁盤上。也就是說EJB容器使用對象串行化不常用的bean並存儲在某個文件中。這個過程在EJB中被稱為passivation。當一個客戶想訪問一個passivated的bean時,EJB容器通過將它由磁盤中讀出,從而再次激活該bean。

ejbPassivate和ejbActivate方法幫助EJB容器解決了一個問題--你不能串行化某些“活動的”操作系統資源,例如網絡連接等。由於大部分的數據庫連接都需要一個網絡連接,這就意味著不能串行化數據庫連接。

如果你在setSessionContext方法中建立了一個數據庫連接,在EJB容器需要passivate該session bean時,你必須對該連接做一些處理,通常是你應該關閉連接並且設置該連接變量為null。當EJB容器調用ejbActivate方法時,再重新建立連接。

提示

不要錯誤地認為在session bean首次創建時會調用ejbActivate。ejbActivate方法僅在ejbPassivate方法被調用後執行。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved