通过上一篇《不吐不快之EJB演练——开篇概述》的介绍,我们已经知道EJB中的Session Bean 又分为有状态和无状态两种类型,那它们之间又有什么区别和联系呢?接下来我们将使用一个简单示例进行演示说明。
示例
1.编写有状态Session Bean接口
/** * 有状态Session Bean接口 * @author Forrest * */ @Remote public interface StatefulEjb { /** * 进行内部计算的方法接口 * @param index */ public void compute(int index); /** * 得到计算结果的方法接口 * @return 返回计算结果 */ public int getResult(); }
2.编写有状态Session Bean实现
/** * 有状态Session Bean的实现类 * @author Forrest * */ @Stateful public class StatefulEjbBean implements StatefulEjb { private int state; @Override public void compute(int i) { state = state + i; } @Override public int getResult() { return state; } }
3.编写客户端调用的方法
public class StatefulEjbClient { /** * 有状态Session Bean的测试客户端方法 * @param args * @throws Exception */ public static void main(String[] args) throws Exception{ InitialContext context = new InitialContext(); //获得远程有状态Session Bean对象 StatefulEjb statefulEjb1 =(StatefulEjb)context.lookup("StatefulEjbBean/remote"); //调用调用Session Bean方法,打印成员变量并进行计算重新赋值变量 for(int i=0; i<=6; i++){ System.out.println(statefulEjb1.getResult()); statefulEjb1.compute(1); } System.out.println("-------------------------------"); //重新获取远程有状态SessionBean对象,模拟另一客户端执行 StatefulEjb statefulEjb2 =(StatefulEjb)context.lookup("StatefulEjbBean/remote"); for(int i=0; i<=6; i++){ System.out.println(statefulEjb2.getResult()); statefulEjb2.compute(1); } } }
执行结果:
有状态Session Bean客户端方法执行打印:
无状态Session Bean客户端方法执行打印:
通过上面的示例,我们可以发现访问有状态Session Bean,不同客户端打印的状态变量结果是不连续的,这说明EJB容器会为每一个客户端分配一个EJB实例,这个实例通过内部变量维护客户端的会话状态,但同时,通过代码我们也可以发现要达到这样的目的,客户端必须持有并维护对有状态Session Bean的引用。
对于无状态Session Bean,实际上是单例模式的一种体现,客户端每次在服务器端内存中访问的都是同一个对象,因此打印的结果是连续的。
总结
通过示例我们可以看到有状态的Session Bean像Http Session那样可以维护会话的状态,这虽然带来了一定的便捷性,但同时增加了EJB容器的负担:不仅要针对不同客户端实例化多个EJB对象,同时还要维护这些对象内部状态,因此降低了系统性能。而反观无状态的Session Bean,则没有此方面的性能问题。
查找资料介绍:应用有状态Session Bean的情况一般满足一下两个条件:
1.客户端的数量比较有限;
2.客户端与服务器之间会话状态信息比较多,较少的交予客户端自己维护就已足够。