程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2EE >> 會話組件(Session Beans)

會話組件(Session Beans)

編輯:J2EE
胡德平 編譯([email protected] www.JavaUnion.org) 會話組件在J2EE服務器中表現為一個客戶端,該客戶端通過調用會話組件方法獲取遠程服務。會話組件為其客戶端完成指定任務,屏蔽了客戶端需要在服務器端執行商業任務的復雜性。 正如其名所暗示,會話組件工作原理類似於交互會話。會話組件是不共享得--它在會話期間只能與一個客戶端交互、一個用戶交互。和交互會話一樣,會話組件沒有持續,當客戶端中斷會話後會話組將也將中斷並不再與客戶端相關聯。 會話組件是非常有用而強大的,因為它將你的客戶端范圍擴展到了遠程服務器--並且它們容易開發。本文將通過簡單示例,為你展示如何編寫、編譯和部署一個簡單的會話組件。 會話組件示例 本文所舉例子是一個在線書店中關於購物車的演示,組件的客戶端需要實現往購物車增加、刪除、查詢等操作功能。為了實現這個例子,你需要完成下面程序的編碼: ·會話組件類(CartEJB.java) ·本地接口(CartHome.java) ·遠程接口(Cart.java) 上述三個文件在所有企業組件(EJB)編程中都是必須的,為了滿足特定應用更多需求,企業組件可能需要更多的幫助類(helper class)。CartEJB會話組件使用了兩個幫助類,即 BookException.java和IdVerifIEr.Java。 如果你安裝了J2EE,上述源碼文件可以在doc/guides/ejb/examples/cart目錄中找到。 會話組件類 本例子中會話組件類命名為CartEJB.,與其它所有的會話組件一樣, CartEJB 類必須滿足以下要求: ·實現SessionBean 接口 ·類定義為公共類(public) ·類不能是抽象類或終極類 ·實現一個或多個ejbCreate方法 ·實現商業方法 ·有無參數的構造方法 ·必須沒有終極方法(finalize method) CartEJB源碼如下:

import java.util.*; 
import Javax.ejb.*; 

public class CartEJB implements SessionBean { 

String customerName; 
String customerId; 
Vector contents; 

public void ejbCreate(String person) throws CreateException { 

if (person == null) { 
throw new CreateException("Null person not allowed."); 
} 
else { 
customerName = person; 
} 

customerId = "0"; 
contents = new Vector(); 
} 

public void ejbCreate(String person, String id) 
throws CreateException { 

if (person == null) { 
throw new CreateException("Null person not allowed."); 
} 
else { 
customerName = person; 
} 

IdVerifier idChecker = new IdVerifIEr(); 
if (idChecker.validate(id)) { 
customerId = id; 
} 
else { 
throw new CreateException("Invalid id: " + id); 
} 

contents = new Vector(); 
} 

public void addBook(String title) { 

contents.addElement(title); 
} 

public void removeBook(String title) throws BookException { 

boolean result = contents.removeElement(title); 
if (result == false) { 
throw new BookException(title + " not in cart."); 
} 
} 

public Vector getContents() { 
return contents; 
} 

public CartEJB() {} 
public void ejbRemove() {} 
public void ejbActivate() {} 
public void ejbPassivate() {} 
public void setSessionContext(SessionContext sc) {} 

} 
會話組件接口(SessionBean) 會話組件接口SessionBean繼承EnterpriseBean 接口,而後者繼承了Serializable 接口。SessionBean 接口定義了ejbRemove, ejbActivate, ejbPassivate 和setSessionContext 方法。CartEJB 類沒有用到這些類,但必須實現它們否則應該定義成抽象類。因此,這些方法在CartEJB類中被聲明為空方法,隨後的內容中將就這些方法何時有什麼用途進行說明。 EjbCreate方法 由於企業組件運行在EJB容器中,所以客戶端無法直接示例化這些組件。只有EJB容器可以示例化企業組件,在本文所述例子中完成實例化需要實現以下步驟: 1. 客戶端調用本地接口的create方法: Cart shoppingCart = home.create("Duke DeEarl","123"); 2. EJB容器實例化企業組件。 3. EJB容器調用CartEJB中對應的ejbCreate方法:

public void ejbCreate(String person, String id) 
throws CreateException { 

if (person == null) { 
throw new CreateException("Null person not allowed."); 
} 
else { 
customerName = person; 
} 

IdVerifier idChecker = new IdVerifIEr(); 
if (idChecker.validate(id)) { 
customerId = id; 
} 
else { 
throw new CreateException("Invalid id: " + id); 
} 

contents = new Vector(); 
} 
典型的, ejbCreate 創建方法初始化企業組件的狀態。前面所提到的ejbCreate方法,如通過create方法傳遞參數初始化客戶名( customerName )和客戶ID( customerId )變量。 企業組件可以有一個或多個ejbCreate 方法,方法的命名必須滿足下面需求: ·訪問控制修飾詞必須是public. ·返回值必須是void. ·參數必須是Java RMI的合法類型 ·修飾詞(modifIEr)不能是static或final. 此外,異常拋出必須包括Javax.ejb.CreateException 和其它你應用中指定需要拋出的異常。如果輸入的參數無效,ejbCreate 方法通常拋出CreateException 異常。 商業方法 會話組件的最根本的用法是實現客戶端所需要的商業任務,客戶端通過create方法返回的參考調用遠程對象的商業方法。從客戶端角度看,商業方法是在本地運行的,但實際上是在遠程會話組件中運行,下面的代碼摘錄描述了CartClIEnt程序中對商業方法的調用過程:

Cart shoppingCart = home.create("Duke DeEarl", "123"); 
. . . 
shoppingCart.addBook("The Martian Chronicles"); 
shoppingCart.removeBook("Alice In Wonderland"); 
bookList = shoppingCart.getContents(); 
The CartEJB class implements the business methods in the following code: 
public void addBook(String title) { 

contents.addElement(new String(title)); 
} 

public void removeBook(String title) throws BookException { 

boolean result = contents.removeElement(title); 
if (result == false) { 
throw new BookException(title + " not in cart."); 
} 
} 

public Vector getContents() { 
return contents; 
} 

商業邏輯的用法必須符合下面的規則: ·方法名不能與EJB體系結構規范中定義的有沖突,如不能命名為ejbCreate、ejbActive等 ·訪問控制修飾符必須是public ·參數類型必須是合法的Java RMI類型 ·修飾詞不能為static或final 方法拋出異常語句可能包括為具體應用而定義的異常,如當書不在購物車中時removeBook方法拋出BookException 異常。 為了指出如無法連接數據庫這樣的系統級錯誤,商業方法需要拋出Javax.ejb.EJBException 異常。當商業方法拋出EJBException時,EJB容器將其包裝成客戶端捕獲得RemoteException 異常。對於應用定義的異常BookException,容器是不會對其進行包裝的,因為EJBException 是RuntimeException 異常的子類。 本地接口 本地接口繼承EJBHome接口,主要用於定義客戶端調度的create方法,如CartClIEnt調用create方法: Cart shoppingCart = home.create("Duke DeEarl", "123"); 在本地接口中每個create 方法與組件類的一個ejbCreate 方法相對應,在CartEJB類中的ejbCreate方法的用法如下:
 
public void ejbCreate(String person) throws CreateException 
. . . 
public void ejbCreate(String person, String id) 
throws CreateException 
比較一下ejbCreate 與CartHome中create 方法的用法:

import java.io.Serializable; 
import java.rmi.RemoteException; 
import javax.ejb.CreateException; 
import Javax.ejb.EJBHome; 

public interface CartHome extends EJBHome { 
Cart create(String person) throws RemoteException, 
CreateException; 
Cart create(String person, String id) throws RemoteException, 
CreateException; 
} 
ejbCreate與 create 方法的用法類似,當在重要的方面是不一致的,本地接口中create方法的使用原則定義如下: ·create方法的參數數量和類型必須與所定義的ejbCreate 方法一致 ·create方法參數和返回類型必須是合法的RMI類型 ·create 方法企業組件遠程接口類型(而djbCreate方法返回空) ·create方法異常拋出語句必須包括java.rmi.RemoteException和javax.ejb.CreateException 遠程接口 遠程接口繼承於Javax.ejb.EJBObject, 定義了客戶端可以調用的商業方法,下面是購物車的遠程接口代碼 :

import java.util.*; 
import javax.ejb.EJBObject; 
import Java.rmi.RemoteException; 

public interface Cart extends EJBObject { 

public void addBook(String title) throws RemoteException; 
public void removeBook(String title) throws BookException, 
RemoteException; 
public Vector getContents() throws RemoteException; 
} 
遠程接口定義方法必須遵循下述原則: ·每個在遠程接口中定義的方法必須與企業組件類中多定義的方對應 ·遠程接口中方法的用法必須與企業組件類中的方法一致 ·方法的參數和返回值必須是合法的RMI類型 ·異常拋出語句必須包括Java.rmi.RemoteException 幫助類 CartEJB 組件有兩個幫助類: BookException和 IdVerifier,其中 BookException 是應用定義的異常而IdVerifIEr 用於在djbCreate方法中驗證customerId 的有效性。幫助類在J2EE應用打包時包含在EJB.jar文件中,與企業組件類在同一包。 狀態管理模式 在為會話組件指定不屬描述符時,不想選擇會話組件的狀態模式:有狀態和無狀態。 有狀態會話組件(Stateful Session Beans) CartEJB 這個例子有三個實例變量:customerName, customerId, 和 contents,這些變量代表了購物車應用的會話狀態。因為CartEJB 具有會話狀態,所以把它叫做有狀態會話組件。 狀態在客戶端與會話組件會話期間保留,當客戶端移交(remove)組件、會話結束後狀態消失。解決這種狀態的短暫性不是什麼問題,然而,因為客戶端和組件之間會話結束後不再需要保留狀態。 無狀態會話組件(Stateless Session Beans) 無狀態會話組件在會話期間不需要為特定的客戶端保存狀態,因而得名。當客戶端調用無狀態組件時,組件實例變量可能會有狀態,但僅僅只是在調用過程中。當方法執行結束後,狀態不再保留。除了方法調用期外,所有的無狀態組件實例都是相等地,允許EJB容器將任何一個實例分配給任意一個苦戶端。 因為無狀態組件可以支持多個客戶端,從擁有大量客戶端的應用來客比有狀態會話組件具有更大的靈活性。通常情況下,應用要求用更多的無狀態組件而非有狀態組件來相應相同的客戶端。 有時,EJB容器會將狀態組件寫到緩存中,但無狀態組件是從來不會這麼做的。因此,相對而言無狀態組件能夠提供比有狀態組件更高的性能。 無狀態組件的本地接口必須有一個無參數的create 方法,同時會話組件也必須有個與其相對應的無參數ejbCreate 方法。 兩種會話組件的選擇 下列情況下,建議選擇有狀態組件: ·在組件創建時必須初始化其狀態 ·組件必須保留客戶端方法商業方法的信息 ·客戶端是交互式應用 既然會話組件的主要目的是在J2EE服務器上表現客戶端功能,更多的會話組件會是有狀態會話組件。不過,在下述情況下建議使用無狀態會話組件: ·組件執行的任務不講究是否對應特定客戶端,如數據庫查詢 ·組件無需保留客戶端對方法調用的信息 會話組件的生命周期 會話組件在其生命周期中有多個狀態,其生命周期由EJB容器所管理而非應用本身。盡管應用無法管理組件的生命周期,但下面關於生命周期的信息對於管理如數據庫連接的資源是有用的。 有狀態會話組件的生命周期 有狀態會話組件的生命周期源於客戶端通過create 方法、EJB容器實例化組件後調用會話組件的setSessionContext 和ejbCreate 方法。此後,組件的商業方法處於可調用的就緒階段。 在就緒階段,EJB容器將判斷組件是否可以處於非活動、鈍化狀態,然後將其從內存轉移到緩存(典型的算法是采用最近最少調用算法),EJB容器調用組件的ejbPassivate 方法實現對組件的鈍化。如果在鈍化階段有客戶端調用該組件的商業方法,EJB容器將激活組件並將其恢復到就緒狀態,然後調用組件的ejbActivate 方法。 在生命周期最後,客戶端調用remove 方法、EJB容器調用組件的ejbRemove 方法,組件實例等待垃圾回收器回收處理。 在客戶端編程中,主要通過調用兩個生命周期相關方法-- create 和 remove 方法實現對生命周期的處理。下圖中所有的方法調用都是由服務器端EJB容器實現的,如 ejbCreate 方法,允許你在組件實例化後進行數據庫連接等操作。 圖 有狀態會話組件生命周期 五狀態會話組件生命周期 因為無狀態會話組件從來不被鈍化,所有它的聲明周期只有兩個階段:在商業方法調用過程中的不存階段在和就緒階段
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved