先前所介紹的Session Bean為Stateless,也就是Session Bean本身不因操作而處於特定狀態,當容器啟動後,Stateless Session Bean建立後會被容器放入池(Pool)中,若有客戶端需要時從池中取出,用畢後歸還池中。
若客戶端的操作分作數個步驟,而操作的過程中需要保留Session Bean的狀態,則可以使用@Stateful標示Session Bean為Stateful Session Bean,Stateful Session Bean與客戶端為一對一的關係,每個客戶端請求時,會話階段期間會配置專屬的Stateful Session Bean,直到客戶端離開(Stateful Session Bean的有效期間結束),或是呼叫了標示為@Remove的方法後,將Stateful Session Bean摧毀回收資源。
以下先使用一個簡單的範例,示範如何使用Stateful Session Bean,首先定義服務介面:
package onlyfun.caterpillar;
import javax.ejb.Remote;
@Remote public interface HelloBean { public String doStep1(String data); public String doStep2(String data); public String finish(String data); }
介面中定義三個方法,模擬客戶端完成某個任務時共需三個步驟,而實作類別如下:
package onlyfun.caterpillar;
import javax.ejb.Remove; import javax.ejb.Stateful;
@Stateful(name="ejb/HelloFacade") public class HelloBeanImpl implements HelloBean { private String step; public String doStep1(String data) { step = data + "processedByStep1/"; return step; }
public String doStep2(String data) { step = step + data + "processedByStep2/"; return step; }
@Remove public String finish(String data) { step = step + data + "processedByFinish"; return step; } }
@Stateful標示這是個Stateful Session Bean,它擁有特定的狀態,程式中使用step成員來模擬,建議Stateful Session Bean必須使用@Remove標示一個方法,表明該方法被呼叫後,容器將可以催毀該Stateful Session Bean而回收資源。
在客戶端的部份,使用以下的程式來模擬:
package onlyfun.caterpillar;
import javax.naming.InitialContext; import javax.naming.NamingException; import javax.rmi.PortableRemoteObject;
public class Main { public static void main(String[] args) throws NamingException { InitialContext context = new InitialContext(); Object obj = context.lookup("onlyfun.caterpillar.HelloBean"); HelloBean hello = (HelloBean) PortableRemoteObject.narrow( obj, HelloBean.class); String result = hello.doStep1("data1"); System.out.println(result); result = hello.doStep2("data2"); System.out.println(result); result = hello.finish("finishData"); System.out.println(result); } }
在程式中,呼叫hello的doStep1()、doStep2()來模擬完成某個操作的幾個步驟,容器端將維護與客戶端的會話階段,保留操作過程中的Session Bean狀態,而最後呼叫finish()方法後,會話完成而回收Session Bean。
程式中還需要的jndi.properties,請參考 第
一個 Session Bean(單機客戶端) 中的內容。
一個執行的結果如下所示:
data1processedByStep1/
data1processedByStep1/data2processedByStep2/
data1processedByStep1/data2processedByStep2/finishDataprocessedByFinish
|
基本上,不建議使用Stateful Session Bean,Stateful Session Bean會為每個客戶端維護一個實例,一但容器判斷系統資源耗用太多,就會作Passivate,將Bean作序列化以儲存在實體媒介,若需要時再作Activate的動作,將已儲存的Bean反序列化,這些都會是效能上的負擔。
建議使用Stateful Session Bean一定要標示@Remove的方法,並在不使用Stateful Session
Bean時明確呼叫該方法,讓容器可以回收資源,可以的話,思考是否可用Stateless Session
Bean,若需要特定狀態時,可以考慮將之儲存在HttpSession、資料庫或相關儲存媒介。
|