EJB2.1学习系列二:session beans
Session Object
会话bean对象有如下特征:
- 为某单个客户端调用
- 具有事务性
- 在基础数据库中更新共享数据
- 生命周期相当较短
- 当EJB容器宕掉时,会被移除掉,客户端需要重新建立一个新的session对象
session beans 又分为stateful(有状态) beans和stateless(无状态) beans,它们的api区别很小。
在客户端来看,一个session object是运行在服务器上的实现了一些业务逻辑的对象。客房端通过session beans定义的组件接口调用session object,通过JNDI(java naming and directory)定位一个session bean的home interface,如下:
1 InitialContext context= new InitialContext(env);
2 Object obj=context.lookup("FirstEjb");
3 HelloWorldHome home=(HelloWorldHome)PortableRemoteObject.narrow(obj,HelloWorldHome.class);
对于session beans发布在本地的情况,即非remote session beans,用如下调用代码:
1 InitialContext context= new InitialContext();
2 HelloWorldHome home=(HelloWorldHome)context.lookup("java:comp/env/ejb/FirstEjb");
一个Ejb容器给客户端提供的服务如下图:
Session Bean’s Remote Home Interface
对于部署在ejb容器中的每个session bean所对应的remote home interface,容器会实现这个接口,并且会让客户端通过JNDI查找到该home interface的实现对象。
remote home interface允许客户端做如下事:
- 创建一个session object
- 移除一个session object
- 得到session bean的javax.ejb.EJBMetaData接口,这样可以让客户端得到session object的相关元数据信息,为实现服务端/客户端低耦合提供可能
创建一个session object
一个home interface可以定义多个create***的方法来创建session object对象,这个方法的参数则可以用来初始化session object的状态。如下:
public interface CartHome extends javax.ejb.EJBHome {
Cart create(String customerName, String account) throws RemoteException,
BadAccountException, CreateException;
Cart createLargeCart(String customerName, String account)
throws RemoteException, BadAccountException, CreateException;
}
客户端则可以如下调用:
cartHome.create(“John”, “7506”);
EJBObject and EJBLocalObject
客户端从来不会直接访问session bean的实现例化对象,对是通过定义的组件接口去调用,而这个接口的实现类则是由ejb容器提供实现。
session ojbect的生命周期
一个session object直到home interface调用create***方法后才会存在并被客户端引用。
一个简单session bean的示例代码
首先,我们脑海里载入平时用spring做开发时的思维方式,一般是先定义核心业务接口,然后写一个具体的接口实现类。
package jcli.cnblogs.ejb;
import java.rmi.RemoteException;
import javax.ejb.EJBObject;
public interface HelloWorldService extends EJBObject{
public String getHello() throws RemoteException;
}
HelloWorldService是我们的业务接口,里面有个getHello的方法。只不过这里的业务接口要继承EJBObject接口。
然后我们要写一个实现类
package jcli.cnblogs.ejb;
import java.rmi.RemoteException;
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
public class HelloWorldServiceImpl implements SessionBean{
private HelloWorldVo helloWorldVo;
/**
*
*/
private static final long serialVersionUID = -3082113467604080824L;
public String getHello() throws EJBException, RemoteException {
System.out.println("server execute getHello method");
if(helloWorldVo == null){
return "create a empty vo....";
}else{
return "create a vo : " + this.helloWorldVo.getId() + " , " + this.helloWorldVo.getName();
}
}
public void ejbCreate() throws javax.ejb.CreateException {
System.out.println("ejbCreate....");
};
public void ejbCreateState(Integer id,String name) throws javax.ejb.CreateException {
System.out.println("ejbCreate....");
helloWorldVo = new HelloWorldVo();
helloWorldVo.setId(id);
helloWorldVo.setName(name);
};
@Override
public void ejbActivate() throws EJBException, RemoteException {
System.out.println("ejbActivate....");
}
//下面省略SessionBean接口其它实现方法
}
大家注意这里的实现类并没有显示实现HelloWorldService接口,而是实现了SessionBean接口,但是里面必需要有HelloWorldService接口里的所有方法(getHello方法),其它的方法先不用关注,后面会讲到。
接下来,作为远程客户端调用,我们还需要一个home interface去创建remote object对象。如下:
package jcli.cnblogs.ejb;
import javax.ejb.EJBHome;
public interface HelloWorldHome extends EJBHome {
HelloWorldService create() throws java.rmi.RemoteException,javax.ejb.CreateException;
HelloWorldService createState(Integer id,String name) throws java.rmi.RemoteException,javax.ejb.CreateException;
}
里面定义的创建session bean的方法必需遵守createXXX形式,如示例中的create(),createState(...)两个方法,一般stateful的session bean,因为其是有状态的,所以一般在创建的时候把初始化其状态值,所以此createXXX方法一般会有参数,但是stateless的bean是无状态的,如果createXXX方法有参数,则会在容器部署启动时报错。因为现在我们是定义的有状态情况,所以crateState(Integer,String)有参数.
细心的读者会可能发现了home interface里定义的方法和HelloworldServiceImpl里的ejbCreate()和ejbCreateState(Integer,Strging)两个方法有点关联,确实是这样。如果home里定义crateXXX方法,则要在SessionBean的实现里定义对应的ejbCreateXXX的方法,且参数个数和类型一致。
客户端用JNDI查找ejb并调用代码如下:
InitialContext initCtx = new InitialContext(env);
Object obj=initCtx.lookup("FirstEjb");
HelloWorldHome home=(HelloWorldHome)PortableRemoteObject.narrow(obj,HelloWorldHome.class);
//当不传任何参数时
HelloWorldService hello = home.create();
String s = hello.getHello();
System.out.println(s);
//当传达参数时
HelloWorldService hello1 = home.createState(1,"tony");
String s1 = hello1.getHello();
System.out.println(s1);
其实当调用createXXX方法时,ejb容器执行如下操作,首先用sessionbean的类(HelloWorldServiceImple.class)newInstance一个实例,然后调用setSessionContext方法把容器的sessionContext对象传进去,然后根据客户调用的createXXX(create和createState)方法来调用ejbCreateXXX(ejbCreate和ejbcreateState)方法。
到此,这个ejb的Demo可以打成jar包并部署到ejb容器中发布了,并用一个远程机器进行调用。当然还要进行相关配置(标准ejb配置ejb-jar.xml)
下载地址:https://files.cnblogs.com/jcli/ejb.zip