我正在阅读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 …Run Code Online (Sandbox Code Playgroud) 我有一个无状态会话bean,它包含一个公共方法,几个私有方法和一些实例级变量.下面是一个伪代码示例.
private int instanceLevelVar
public void methodA(int x) {
this.instanceLevelVar = x;
methodB();
}
private void methodB() {
System.out.println(instanceLevelVar);
}
Run Code Online (Sandbox Code Playgroud)
我所看到的是,methodB正在打印未传递给MethodA的值.最好我可以告诉它从同一个bean的其他实例打印值.什么会导致这个?
我应该指出代码在99.9%的时间内按预期工作.但是,.01%对我来说是一个严重的问题/担忧.
我明白,如果我有不同的公共方法,那么我可能不会在调用之间获得相同的bean,这会导致这种行为.但是,在这种情况下,唯一的调用是单个公共方法.容器(在这种情况下是Glassfish)是否仍会在私有方法调用之间交换bean?
(编辑)我将"类级别"重命名为"实例级别",因为这引起了一些混乱.
我从未使用过有状态的EJB.我知道有状态EJB对java客户端很有用.
但我想知道:在哪种情况下在Web应用程序中使用它们?如何?我们应该把这些有状态的bean放在Session中吗(因为无状态的http)?
这是一个好习惯吗?(没有过多讨论有状态与无状态)
我正在学习EJB3,我很好奇什么时候使用SFSB很方便?当SFSB轻易解决一些复杂的问题时,我找不到任何好的例子.
实际上我看到SLSB可以用作网络服务,这很方便.但我不知道何时使用SFSB.我只看到它的问题,因为我们应该学习一些关于它的东西,我们应该编写一个由注释组成的代码,然后我们应该使用恼人的查找...而且我们没有得到任何好的回报.
例如,我们不能使用SLSB中的SFSB,因为有状态对象只能用于有状态上下文.我们不能在servlet中使用DI,而是应该使用JNDI查找手动创建SFSB实例,然后将其放入HttpSession对象中.它不能是网络服务.
我在SFSB中看到的唯一好处是事务管理.但我认为,当我们真的需要一个交易并且我们不需要DB时,这种情况很少见.我可以想象,当我们将数据存储在XML文件中并使用SFSB中的事务管理来管理非关系数据库时,它确实非常有用.
我几乎可以肯定我完全错了,所以给我一些非常好的SFSB用法示例.
我们目前有一个注入Servlet的有状态bean.问题是有时候我们会Caused by: javax.ejb.ConcurrentAccessException: SessionBean is executing another request. [session-key: 7d90c02200a81f-752fe1cd-1]在有状态bean上执行一个方法.
public class NewServlet extends HttpServlet {
@EJB
private ReportLocal reportBean;
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
String[] parameters = fetchParameters(request);
out.write(reportBean.constructReport(parameters));
} finally {
out.close();
}
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,constructReport将检查是否需要打开与Report中指定的数据库的新连接,之后在根据指定的参数构建的查询中构建HTML中的Report.
我们选择在无状态bean上使用有状态bean的原因是因为我们需要打开与未知数据库的数据库连接并对其执行查询.对于无状态bean,使用每个注入的bean实例重复打开和关闭数据库连接似乎非常低效.