1

使用EJB(3.x),您可以選擇Session Bean:@Stateful@Stateless。如果我沒有理解這兩個選項背後的基礎:GlassFish如何將客戶端請求映射到會話

  • @Stateful - 爲每個用戶/客戶端獲取自己的,因此通常不集中;在多個請求
  • @Stateless保持狀態 - 不維護請求之間的狀態,因此通常彙集所以每個新的客戶端請求獲得一個新豆

我在這裏的核心問題是很簡單,但是有幾個迷你我有與之相關的問題:我的POJO設計在@Stateful豆與@Stateless之間有什麼不同?換句話說,如果我有一個實現了Hello接口的HelloWorld bean,那麼POJO的設計如何改變取決於我是否希望它是有狀態的?

切到這一點:

  • 並應用容器(在我的情況的GlassFish)強加給取決於它是否是有狀態的,沒有什麼EJB不同的限制?
  • @Stateful的情況下,來自同一個用戶/客戶端的客戶端請求如何映射到正確的bean(保持客戶端的狀態與先前的請求不一致)?
  • 會話bean何時死亡?我假設它在@Stateless的請求完成之後立即生效,但對@Stateful沒有任何線索。

在此先感謝您的任何澄清。

回答

2

關於核心問題:「請問我的POJO設計@Stateful豆與@Stateless之間的不同」:

你的hello world例子是@Stateless會話bean的一個很好的例子:在實現了沒有狀態(沒有類實例變量)。它不會對狀態做任何假設。如果你確實需要@Stateless bean中的「更多信息」來查找它,(重新)計算它等等。如果你打破了這個規則並在bean上定義了實例變量,那麼你就不能保證這些信息會成爲你期望的它在每個bean的調用上:不要這樣做。

@Stateful bean的設計將保留容器在bean的生命期內保留的內部狀態(類實例變量)該bean必須是可序列化的。關於在會話的整個生命週期內保持bean的相關信息,存在非常實際的運行時成本(內存,以及圍繞第二個切線問題來管理問題,特別是在集羣環境中) - 所以僅在適當的時候使用它(這證明了@Stateless bean的存在)。

例如,考慮一個簡單的註冊頁面:輸入用戶名,電子郵件地址等,然後輸入「你確定」嗎? @Stateful bean可以保存這些臨時信息,直到您準備將其提交到後端。

谷歌的例子;這裏是一個:http://docs.redhat.com/docs/en-US/JBoss_Enterprise_Application_Platform/6/html/Beta_Documentation/Stateful_Session_Bean_Example.html

如何將客戶端映射到正確的@Stateful bean是否真正依賴於實現(不指定),但是您可以期望它的管理方式類似於您的Servlet會話信息的維護方式。也就是說,不要將Servlet會話與@Stateful會話混淆, - 它們根本不是一回事。

對於@Stateful bean中的Java EE 5/6,使用@Remove註釋一個方法,當您的客戶端調用該方法時,它將被釋放回以太。除此之外,只要您持有對@Stateful bean的引用(即在您的Servlet會話中),就可以期待@Stateful bean在您需要時可以使用。

參見:http://docs.oracle.com/javaee/5/tutorial/doc/bnbmt.html

0

1)您的EJB/Pojo真的不知道區別。作爲一名開發人員,但在代碼級別,無狀態bean看起來非常像一個有狀態的bean。生命週期和回調實際上是相同的,區別在於客戶端對該生命週期有更多的控制權,而對於無狀態bean,容器可以控制該生命週期。

2)您的客戶端只維護Session Bean實例的副本。因此,例如,在Web容器中,您可以簡單地將實例填充到會話中。你不想做的只是不斷地爲每個請求插入一個有狀態會話bean(使用@EJB),因爲每次都會創建一個新bean。最好檢查你的會話,如果它不存在,然後正常查看它。

3)有狀態bean可以有一個用@Remove註釋的方法。當你調用這個方法時,這個bean就被銷燬了。如果您不調用此方法,那麼容器具有超時功能,在某些配置的持續時間後會自動獲取會話Bean。沒有期望有狀態的bean在服務器重啓的情況下倖存下來(儘管在集羣環境中該合同可能會有所不同)。

還有一大堆遺留的EJB 2行爲,大部分都是可行的,你只需要跳過這些環節去實現它,現代的東西就更容易了。

0
  • 如果您在無狀態會話Bean中擁有實例變量,則它們的值將毫無意義(實際上)。這是因爲您永遠不知道將從實例池中檢索哪個無狀態會話Bean實例來爲請求提供服務。

  • 無狀態會話Bean僅在容器決定殺死它們時纔會死亡。它們根據需要被實例化,並且只有在容器決定銷燬容器時纔會被銷燬(例如,如果它決定使實例池變小)。你說你認爲他們在請求後被銷燬,但這是不正確的。請求後,它們返回到實例池並保持準備好爲下一個請求提供服務。

0

因爲問題是廣泛的,我會盡量回答不久,並提供鏈接到更多信息。

應用程序容器(在我的情況GlassFish)對EJB施加什麼不同限制取決於它是否是有狀態的?

你的情況主要區別是告訴與以下報價從規格:

無狀態會話bean會話bean,它的實例沒有 會話狀態。這意味着所有bean實例在不涉及爲客戶端調用的方法提供服務時都是 。術語「無狀態」表示對於特定客戶,實例沒有狀態 。但是,實例 的實例變量可以包含跨客戶端調用的方法調用的狀態。這種狀態的例子包括開放的數據庫連接和對企業bean對象的對象引用 。

在@Stateful的情況下,如何從同一個用戶/客戶端一個客戶端的請求被映射到正確的豆(一種從以前要求保持客戶端的狀態)?

在客戶端,您必須存儲對有狀態會話bean的業務接口的引用。你從EJB容器中獲得的這個對象。它是容器創建的對象,包含有關如何定位服務器端對象的詳細信息。有關GlassFish中這些代理的一些信息可以從以下網址找到:

會話Bean何時死亡?在@Stateless完成請求之後,我會立即假定它,但對@Stateful沒有任何線索。

否,無狀態會話bean(SLSB)在請求後不會死亡。無狀態會話bean的壽命爲:

  1. 它是在容器決定的時候創建的。這在 自然發生在它使用前的某個點上,但在其他情況下,它在 容器的手中。 SLSB創建後,它被放置到池中。
  2. 當某些客戶端需要調用SLSB中的方法時,在方法調用期間有一個實例從池中被帶走。方法調用完成後,實例 返回到池。然後這個實例(其他人)準備好爲下一個客戶提供服務。

    1. 新實例由容器創建時JNDI查找或:當容器決定調整池的大小

    有狀態會話bean(SFSB)的壽命大致如下

  3. 生命SLSB的結束注射發生。
  4. 在其生命週期中,SFSB可以服務多個方法調用。它也可以被鈍化(基本上存儲到光盤以節省資源)並再次激活。
  5. 當調用remove方法或超時(SFSB未使用一段時間)時,SFSB的壽命結束。容器通常具有實現特定的默認超時時間,並且可以調整超時時間。在Java EE 6(EJB 3.1)中,可以通過StatefulTimeout以每個bean爲基礎調整此超時。

當發生系統異常時,會話bean的附加實例將被丟棄。系統異常是RuntimeException(未標記爲應用程序異常)或java.rmi.RemoteException。事實上,SLSB的實例被丟棄對客戶端來說是透明的。下一次電話肯定會由SLSB的其他實例 服務。對於SFSB,所有未來的業務方法調用都將失敗,因爲SFSB的服務器端實例不再存在。詳細信息可以從EJB 3.1規範第14章中找到。

可以從EJB 3.1規範(4.6,4.7)中找到生命週期的詳細定義。說明比上面更詳細,並有圖表可在Java EE 6 Tutorial

什麼是對你好的服務設計的主要功效:

@Stateless 
public class HelloStateless implements HelloRemote { 
    @Override 
    public String getGreeting(String name) { 
     return "Hi " + name; 
    } 
} 


/** 
* This design is not possible for Stateless, because 
* subsequent calls to setName and getGreeting can be 
* handled by two different instances. For stateful it 
* is fine, because we use one exclusively one instance. 
*/ 
@Stateful 
public class HelloStateful { 

    private String name; 
    public void setName(String name) { 
     this.name = name; 
    } 

    public String getGreeting() { 
     return "Hi " + name; 
    } 
}