Sta*_*lly 89 java ejb java-ee stateful-session-bean ejb-3.1
我正在阅读Java EE 6教程,我试图理解无状态和有状态会话bean之间的区别.如果无状态会话bean在方法调用之间不保持其状态,为什么我的程序按照它的方式运行?
package mybeans;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
@LocalBean
@Stateless
public class MyBean {
private int number = 0;
public int getNumber() {
return number;
}
public void increment() {
this.number++;
}
}
Run Code Online (Sandbox Code Playgroud)
客户端
import java.io.IOException;
import javax.ejb.EJB;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.WebServlet;
import mybeans.MyBean;
import java.io.PrintWriter;
@WebServlet(name = "ServletClient", urlPatterns = { "/ServletClient" })
public class ServletClient extends HttpServlet {
private static final long serialVersionUID = 1L;
@EJB
MyBean mybean;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
mybean.increment();
out.println(mybean.getNumber());
}
}
Run Code Online (Sandbox Code Playgroud)
我希望getNumber每次返回0,但它返回1并且在我的浏览器中重新加载servlet会增加更多.问题在于我对无状态会话bean的工作原理的理解,当然也不是库或应用服务器.有人可以给我一个简单的hello world类型的无状态会话bean示例,当您将其更改为有状态时,其行为会有所不同吗?
Pas*_*ent 134
无状态会话Bean(SLSB)不依赖于一个客户端,并且无法保证一个客户端在每个方法调用时获取相同的实例(某些容器可能会在每个方法调用会话中创建和销毁bean,这是特定于实现的决策,但实例通常是合并的 - 我没有提到集群环境).换句话说,尽管无状态bean可能具有实例变量,但这些字段并非特定于一个客户端,因此不要在远程调用之间依赖它们.
相比之下,有状态会话Bean(SFSB)在其整个生命中专门用于一个客户端,没有交换或汇集实例(可能在钝化后从内存中逐出以节省资源但这是另一个故事)并保持会话状态.这意味着bean的实例变量可以在方法调用之间保持相对于客户端的数据.这使得相互依赖的方法调用成为可能(一种方法所做的更改会影响后续的方法调用).多步骤流程(注册流程,购物车,预订流程......)是SFSB的典型用例.
还有一件事.如果您正在使用SFSB,那么您必须避免将它们注入到多线程的类中,例如Servlet和JSF托管bean(您不希望它被所有客户端共享).如果要在Web应用程序中使用SFSB,则需要执行JNDI查找并将返回的EJB实例存储在HttpSession对象中以供将来活动.像这样的东西:
try {
InitialContext ctx = new InitialContext();
myStateful = (MyStateful)ctx.lookup("java:comp/env/MyStatefulBean");
session.setAttribute("my_stateful", myStateful);
} catch (Exception e) {
// exception handling
}
Run Code Online (Sandbox Code Playgroud)
duf*_*ymo 90
重要的区别不是私有成员变量,而是将状态与特定用户相关联(想想"购物车").
有状态的有状态会话bean就像servlet中的会话一样.即使没有Web客户端,有状态会话bean也允许您的应用仍然拥有该会话.当应用服务器从对象池中提取无状态会话bean时,它知道它可以用于满足任何请求,因为它不与特定用户相关联.
有状态会话bean必须首先发送给获得它的用户,因为他们的购物车信息应该只为他们所知.应用服务器确保这样做.想象一下,如果您可以开始购物,那么您的应用程序会有多受欢迎,然后当我出现时,应用服务器会向您发送有状态会话bean!
所以你的私人数据成员确实是"州",但它不是"购物车".尝试重做您的(非常好的)示例,使增量变量与特定用户相关联.增加它,创建一个新用户,看看他们是否仍然可以看到递增的值.如果操作正确,每个用户都应该只看到他们的计数器版本.
cle*_*tus 18
在这种情况下,无国籍和有状态并不意味着你所期望的.
EJB的有状态是指我称之为会话状态.典型的例子是航班预订.如果它包含三个步骤:
想象一下,每个都是对会话bean的方法调用.有状态会话bean可以维护这种对话,因此它会记住调用之间发生的事情.
无状态会话bean没有这种会话状态的容量.
会话bean(无状态或有状态)中的全局变量完全是另一回事.有状态会话bean将创建一个bean池(因为bean一次只能在一个对话中使用),而无状态sesion bean通常只有一个实例,这将使全局变量起作用,但我不认为这必然得到保证.
好问题,
试试这个代码(改变 MyBean Stateful/Stateless。):
import javax.ejb.LocalBean;
import javax.ejb.Stateful;
import javax.ejb.Stateless;
@LocalBean
@Stateless
public class MyBean {
private int number = 0;
public int getNumber() {
return number;
}
public void increment() {
this.number++;
}
}
Run Code Online (Sandbox Code Playgroud)
小服务程序_1
import java.io.IOException;
import javax.ejb.EJB;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.WebServlet;
import java.io.PrintWriter;
@WebServlet(name = "ServletClient", urlPatterns = { "/ServletClient" })
public class ServletClient extends HttpServlet {
private static final long serialVersionUID = 1L;
@EJB
MyBean mybean;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
mybean.increment();
out.println(mybean.getNumber());
}
}
Run Code Online (Sandbox Code Playgroud)
Servlet_2
import java.io.IOException;
import javax.ejb.EJB;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.WebServlet;
import java.io.PrintWriter;
@WebServlet(name = "NewServletClient", urlPatterns = { "/NewServletClient" })
public class NewServletClient extends HttpServlet {
private static final long serialVersionUID = 1L;
@EJB
MyBean mybean;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
mybean.increment();
out.println(mybean.getNumber());
}
}
Run Code Online (Sandbox Code Playgroud)
案例:MyBean -@Stateless
http://localhost:8080/MYServletDemo/ ServletClient
1
http://localhost:8080/MYServletDemo/ ServletClient
2
http://localhost:8080/MYServletDemo_war_exploded/ newServletClient
3
http://localhost:8080/MYServletDemo/ ServletClient
4
案例:MyBean -@Stateful
http://localhost:8080/MYServletDemo/ ServletClient
1
http://localhost:8080/MYServletDemo/ ServletClient
2
http://localhost:8080/MYServletDemo/ newServletClient
1
http://localhost:8080/MYServletDemo/ ServletClient
3
两种主要类型的会话 bean 之间的主要区别是:
无状态 Bean
- 无状态会话 Bean是那些与调用其方法的客户端没有对话状态的会话 Bean。出于这个原因,他们可以创建一个可用于与多个客户端交互的对象池 。
- 性能明智的无状态 bean更好,因为它们没有每个客户端的状态。
- 它们可以并行处理来自多个客户端的多个请求。
有状态的 Bean
- 有状态会话 bean 可以同时保持与多个客户端的会话状态,并且任务不在客户端之间共享。
- 会话完成后,状态不会保留。
- 容器可以将状态序列化并存储为陈旧状态以备将来使用。这样做是为了节省应用程序服务器的资源并支持 bean 故障。
| 归档时间: |
|
| 查看次数: |
92161 次 |
| 最近记录: |