前边的文章中,简单的介绍了ejb的三种bean,我们这片文章通过实例来看一下有状态的会话bean和无状态的会话bean的区别。
我们建立一个ejb项目,分别创建两个接口, 两个实现类,每个类中都有相同的方法,并在每个类中有一个静态变量,用来存放数据。代码如下所示。至于如何发布ejb项目到JBoss中,请参见Ejb框架搭建
/**
* 有状态sessionbean的接口
* @author hongjie
*
*/
public interface EjbStatefulSession {
public String Count();
}
/**
* 无状态bean的sessionbean的接口
* @author hongjie
*
*/
public interface EjbStatelessSession {
public String Count();
}
/**
* 有状态bean的实现类
* @author hongjie
*
*/
@Remote
@Stateful
public class EjbStatefulSessionBean implements EjbStatefulSession {
//静态变量,用来存放数据,看两次调用返回的数据是否是同一份数据
private Integer i=0;
//每次返回的数据+1
@Override
public String Count() {
i=i+1;
return i.toString();
}
}
/**
* 无状态bean的实现类
* @author hongjie
*
*/
@Remote
@Stateless
public class EjbStatelessSessionBean implements EjbStatelessSession {
//静态变量,用来存放数据,看两次调用返回的数据是否是同一份数据
private Integer i=0;
//每次返回的数据+1
@Override
public String Count() {
i=i+1;
return i.toString();
}
}
我们在创建一个客户端,在客户端的Main方法中,我们要创建四个上下文对象,其中两个上下文对象创建有状态EJB,另外两个上下文对象创建无状态EJB对象,这四个EJB对象分别调用Count方法。
package com.tgb.ejb.client;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import junit.framework.TestCase;
import com.tgb.ejb.EjbStatefulSession;
import com.tgb.ejb.EjbStatelessSession;
public class EjbSessionBeanClient extends TestCase {
public static void main(String[] args) {
//jndi所用的url
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.provider.url", "localhost:1099");
try {
//上下文ctx0
InitialContext ctx0 = new InitialContext(props);
//有状态EJB对象
EjbStatefulSession statefulSession = (EjbStatefulSession) ctx0
.lookup("EjbStatefulSessionBean/remote");
for (int i = 0; i < 5; i++) {
System.out.println("有状态bean第一次调用"+statefulSession.Count());
}
//上下文ctx1
InitialContext ctx1 = new InitialContext(props);
//有状态EJB对象
EjbStatefulSession statefulSession1 = (EjbStatefulSession) ctx1
.lookup("EjbStatefulSessionBean/remote");
for (int i = 5; i < 10; i++) {
System.out.println("有状态bean第二次调用"+statefulSession1.Count());
}
} catch (Exception e) {
System.out.println(e.toString());
}
try {
//上下文ctx2
InitialContext ctx2 = new InitialContext(props);
for (int i = 0; i < 5; i++) {
//无状态EJB对象
EjbStatelessSession statelessSession2 = (EjbStatelessSession) ctx2
.lookup("EjbStatelessSessionBean/remote");
System.out.println("无状态bean第一次调用"+statelessSession2.Count());
}
} catch (Exception e) {
System.out.println(e.toString());
}
//上下文ctx3
InitialContext ctx3;
try {
ctx3 = new InitialContext(props);
for (int i = 0; i < 5; i++) {
//无状态EJB对象
EjbStatelessSession statelessSession3 = (EjbStatelessSession) ctx3
.lookup("EjbStatelessSessionBean/remote");
System.out.println("无状态bean第二一次调用"+statelessSession3.Count());
}
} catch (NamingException e) {
e.printStackTrace();
}
}
}
我们可以看到输出值如下,有状态EJB对象,每次调用都是从1到5,说明我们每次调用有状态EJB对象,EJB容器都会为我们提供一个新的EJB对象。而无状态EJB对象,每次调用都是从上一次增加1 ,说明我们一直用的是一个EJB对象。所以如果我们不需要保存用户数据的话,那么我们就是用无状态EJB对象,无状态EJB对象是采用的是实例池技术管理的EJB对象,而有状态的EJB对象是激活管理方式进行管理的!
EJB对象的访问方式还有本地和远程之分,在本地访问方式中,不通过socket协议,在同一个jvm中进行通讯,而远程访问方式要通过socket协议,产生网络连接,所以速度会比本地方式慢。但是在实际中本地访问方式还不是很长用。