2016-06-10 75 views
0

我正在嘗試創建@Stateful,@Stateless和@Singleton EJB bean的簡單示例,以幫助我更好地理解差異。問題是,當我使用@Stateful,@Stateless或@Singleton註解中的任何一個註釋bean時,根本沒有區別。與有狀態,無狀態和單例EJB bean相同的結果

這裏是bean:

import javax.ejb.Singleton; 
import javax.ejb.Stateful; 
import javax.ejb.Stateless; 


    @Stateful 
    public class Bean { 
     private int counter = 0; 

     public int getCounter(){ 
      return counter++; 
     } 
    } 

這裏是Servlet的客戶:

import java.io.IOException; 
import java.io.PrintWriter; 

import javax.ejb.EJB; 
import javax.servlet.ServletException; 
import javax.servlet.annotation.WebServlet; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

import javaeetutorial.converter.ejb.Bean; 

@WebServlet(urlPatterns="/") 
public class Client extends HttpServlet{ 

    @EJB 
    Bean bean; 

    protected void processRequest(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException { 
     response.setContentType("text/html;charset=UTF-8"); 
     PrintWriter out = response.getWriter(); 
     out.println("<html lang=\"en\">"); 
     out.println("<head>"); 
     out.println("<title>test</title>"); 
     out.println("</head>"); 
     out.println("<body>"); 
     out.println("<h1>Servlet ConverterServlet at " + 
       request.getContextPath() + "</h1>"); 
     try { 
      out.println("<form method=\"get\">"); 
      out.println("<input type=\"submit\" value=\"Submit\">"); 
      out.println("</form>"); 
      out.println("<p>" + bean.getCounter() + "</p>");  
      out.println("<p>" + bean + "</p>"); 
     } finally { 
      out.println("</body>"); 
      out.println("</html>"); 
      out.close(); 
     } 
    } 

    @Override 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException { 
     processRequest(request, response); 
    } 

    @Override 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException { 
     processRequest(request, response); 
    } 

} 

我預期的結果是:

@Statefull - 當每一個不同的客戶端按按鈕看到從0開始計數

@Singleton - 當任何客戶端按e鈕只看到一個計數

@Stateless - 我不知道會發生

+0

描述你正在運行的測試 – fantarama

回答

0

的問題,你必須是該webservlet被實例化一次(或至少每個請求不是一次,那是你需要清楚地看到有什麼區別),所以它是bean實例。因此,使用哪種類型的bean(有狀態,無狀態,單例)沒有區別,因爲Bean實例始終依賴於同一個servlet實例。

如果你想使用requestScoped資源,與註釋,你會算多少次已經要求計數器(所有請求共享同一個實例),與狀態你會看到多少次客戶請求的計數器,並與無狀態將取決於。但是,因爲計數器是一個狀態,所以使用一個無狀態bean(查看名稱)是沒有意義的。你可以理解爲無狀態的 ejb,所以每次需要bean時,服務器都會獲取無狀態池的實例。一個優點是bean的性能,因爲它們已經被創建到池中(檢查無狀態池配置),它們使用起來非常快。

你可以找到更多的信息here

1

正是預期的結果是:

  • @Stateful - 有狀態會話Bean有超時,所以你應該從來沒有注入一個有狀態的會話bean到一個長壽命的對象,如一個servlet。相反,你應該只查看它們並使用它們(可能通過將引用插入到HttpSession中)。預期的結果是bean實例及其計數器將被所有請求共享,並且如果發出併發請求,則每個請求都會阻塞等待對有狀態會話bean的訪問(嘗試向getCounter方法添加睡眠,然後發出請求來自多個瀏覽器標籤/窗口)。如果您在一段時間內沒有提出請求,則該bean將被刪除,這將導致所有後續請求失敗;您可以使用@StatefulTimeout(value=1, unit=TimeUnit.SECONDS)輕鬆觀察此情況。

  • @Singleton - bean實例及其計數器將被所有請求共享。默認情況下,singleton使用容器管理的併發性,因此一次只能有一個請求在一個方法中被允許。再次,您可以在getCounter方法中添加一個睡眠來觀察這一點。

  • @Stateless - 根據您的應用程序服務器的池配置,可能會根據併發請求的需要創建多個bean實例,並且可能會跨請求重用bean實例。同樣,您可以爲getCounter方法添加一個睡眠,並通過多個瀏覽器選項卡/窗口發出請求來觀察這一點。無狀態會話bean旨在用於封裝其他EJB服務(例如事務,安全性,調度等),因此成員變量只應用於緩存可以使用的狀態,而不管客戶端如何緩存(例如,緩存對DataSource,UserTransaction等),而不是存儲狀態。