通过上一篇《不吐不快之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);
}
}
}
(注:无状态 S essionBean 的示例与给出的有状态 Session 示例代码基本相同,只是将实现部分的 @Stateful 注解换成 @Stateless , JNDI 远程访问做好对应即可。程序实现环境: M yEclipse10.7 , JBoss 5.0.0.GA )
执行结果:
有状态Session Bean客户端方法执行打印:
无状态Session Bean客户端方法执行打印:
通过上面的示例,我们可以发现访问有状态Session Bean,不同客户端打印的状态变量结果是不连续的,这说明EJB容器会为每一个客户端分配一个EJB实例,这个实例通过内部变量维护客户端的会话状态,但同时,通过代码我们也可以发现要达到这样的目的,客户端必须持有并维护对有状态Session Bean的引用。
对于无状态Session Bean,实际上是单例模式的一种体现,客户端每次在服务器端内存中访问的都是同一个对象,因此打印的结果是连续的。
总结
通过示例我们可以看到有状态的Session Bean像Http Session那样可以维护会话的状态,这虽然带来了一定的便捷性,但同时增加了EJB容器的负担:不仅要针对不同客户端实例化多个EJB对象,同时还要维护这些对象内部状态,因此降低了系统性能。而反观无状态的Session Bean,则没有此方面的性能问题。
查找资料介绍:应用有状态Session Bean的情况一般满足一下两个条件:
1.客户端的数量比较有限;
2.客户端与服务器之间会话状态信息比较多,较少的交予客户端自己维护就已足够。