2016-06-10 130 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等),而不是存储状态。