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


原文地址:https://www.cnblogs.com/jcli/p/2379734.html