首页 > 代码库 > EJB初级篇--EJB组件之会话Bean

EJB初级篇--EJB组件之会话Bean

      上篇博文中我们已经详解介绍了什么是EJB。其实最简单的说:EJB就是运行在独立服务器上的组件,客户端是通过网络EJB对象进行调用。而我们常说的企业Bean组件可以分为三种类型:会话Bean消息驱动Bean实体Bean。依据应用设计的不同,开发者可以选择适合应用的组件类型。下面几篇博文中我会为大家分别详细的介绍这三种企业Bean组件。本篇博文则就先来介绍介绍会话Bean吧。

      首先来介绍一下,什么是会话Bean。会话Bean能够完成客户所要求的业务操作,它是含有业务逻辑的可重用组件,并能够用于业务过程。简单一句话:会话Bean就是用来实现业务逻辑的。

      下面就详细介绍会话Bean的主要内容,包括以下两点:一是会话Bean的生命周期;二则是会话Bean的子类型。

-----------------------------------生  命  周  期-----------------------------------

      

      先由一个例子引入:如果客户端代码调用用于完成“登录登记”的会话Bean,则EJB容器需要完成会话Bean组件实例的创建。在后续操作中,如果客户不再与该实例交互,应用服务器有可能会销毁它。也就是说:会话Bean实例开始于客户获得其引用时,而终止于客户会话的终结。映射到会话Bean的生命周期,可以说:客户会话(Client Session)的持续期就决定了使用中的会话Bean的存活期,也就是生命周期。而一般情况下,客户会话的持续期是比较的,所以会话Bean的实例也是存活短暂的对象

 

      知道了会话Bean的生命周期后,那么操作会话Bean生命周期的又是什么呢?答案就是EJB容器。不仅仅是会话BeanEJB容器管理着EJB全部组件的生命周期。例如客户超时,EJB容器将会销毁会话Bean实例。

 

-----------------------------------  类 型--------------------------------------

      

      会话Bean存在两种子类型:无状态会话Bean和有状态会话Bean,用于建模不同类型的会话。

一、无状态会话Bean

      无状态会话Bean适用于只需单个请求会话即可完成的业务过程。这样,EJB组件不需要维护方法调用间的状态变更信息

      为了实现有效的Bean实例处理,EJB容器经常会使用实例池技术。下图是无状态会话Bean的实例池。我们可以清晰的导出无状态会话Bean的内部机制。

计算机生成了可选文字:客户业务接口,·远程接口十/画困Invoke()、\、跳日n实例、

                                                                                                                   1.1

      由于无状态会话Bean不含会话状态,因此同一无状态会话Bean类的所有实例对于客户而言都是等效的。而且无状态会话Bean不保留历史会话信息,所以它对于调用其本身的客户也并不关注。因此,任何无状态会话Bean都能够服务任何客户请求。因为这些无状态会话Bean都是一样的。

      了解了原理之后,来一个很简单的小Demo来加深对无状态会话Bean的理解吧。首先是EJB的服务器端:

/**
* @ClassName: 无状态会话Bean Demo接口类
*@Description: EJB服务器端接口类
*@author 孙丽端
* @date 2014年11月28日20:22:51
*/
package com.tgb.ejb;
 
public interfaceStatelessEjb {
publicvoid compute(int i);
publicint getResult();
}

/**
* @ClassName: 无状态会话Bean Demo实现类
*@Description: EJB服务器端实现类
*@author 孙丽端
* @date 2014年11月28日20:22:51
*/
package com.tgb.ejb;
 
importjavax.ejb.Remote;
importjavax.ejb.Stateless;
 
@Stateless
@Remote
public classStatelessEjbBean implements StatelessEjb {
 
privateint state;
 
@Override
publicvoid compute(int i) {
    state= state +i;
 
}
 
@Override
publicint getResult() {
    //TODO Auto-generated method stub
    return state;
}


      其次来看看EJB的客户端调用代码实现,客户端调用的是服务器端接口类的方法:

/**
* @ClassName: 无状态会话Bean Demo客户端类
*@Description: EJB客户端类
*@author 孙丽端
* @date 2014年11月28日20:22:51
*/
package com.tgb.ejb;
 
importjavax.naming.InitialContext;
importjavax.naming.NamingException;
 
public classStatelessEjbClient {
publicstatic void main(String[] args) throws NamingException {
InitialContextcontext = new InitialContext();
 
StatelessEjbejb1 =(StatelessEjb)context.lookup("StatelessEjbBean/remote");
System.out.print(ejb1.getResult());
ejb1.compute(1);
System.out.print(ejb1.getResult());                
ejb1.compute(1);
System.out.print(ejb1.getResult());                
 
StatelessEjbejb2 =(StatelessEjb)context.lookup("StatelessEjbBean/remote");
System.out.print(ejb2.getResult());                
ejb2.compute(1);
System.out.print(ejb2.getResult());                
ejb2.compute(1);
System.out.print(ejb2.getResult());        
}
 
}

      最后的运行结果是:

 

计算机生成了可选文字:豆prob.ems石JaVodo可亘。些.orotion厦面,o.e不品servers<terminated>StatelessEjbClient[JavaApplication]C:\JavaMD叭bin丫avaw.exe(2012234

 

二、有状态会话Bean

      有状态会话Bean适用于需要若干请求形成才可完成的业务过程。这样,EJB组件就需要维护方法调用间的状态变更信息,最形象的就是淘宝购物车的状态了。在用户浏览商品到加入购物车直至购买,我们必须跟踪用户的状态,并且为单个客户保存状态信息。

 

      1.1是无状态会话Bean的实例池,EJB容器只需要在实例池中维护若干个Bean实例,便能服务大量的并发的客户。可是对于有状态会话Bean来说,这样是远远不够的。

      在有状态会话Bean中各个Bean实例中存储的状态信息仅是单个客户的。如果和无状态会话Bean的处理一样,只是简单的将实例全部放置实例池中,当大量的并发客户操作时,内存中运行的有状态会话Bean实例就会过多而失去控制。

      因此,为了限制内存中Bean实例的数量EJB容器使用了挂起激活两个操作。咱们先来说说挂起吧。

      挂起是什么呢?就和束之高阁一样的,把它先保存起来,以后再用。在这里就是当有状态会话Bean实例暂时没有参与到客户请求中时,容器就有可能挂起它,它的会话状态会被安全的保存下来,而且其释放的内存可以供其他应用(EJB实例)使用。具体的挂起原理如下图所示:

计算机生成了可选文字:客户别2:获胶最近最少使用业务接口,实例·调用牛Bean实钵·@PrePassivate妇丫+口接程}匹4:翩讹Be。n实例的伏态,,靳或召琳雳瀚尚Bean料浪思并晰+-曰

图 2.1

      这时候读者朋友可能会问,那么EJB容器怎么知道该挂起那个Bean实例呢?上图中有提到,大部分容器使用最近最少使用的挂起策略,即简单的挂起最近没有使用到的有状态会话Bean实例。

 

      一旦被挂起的有状态会话Bean实例的客户再次调用它,被挂起的会话状态将重新回到有状态会话Bean实例中。注意我说的是“被挂起的会话状态”,激活的有状态会话Bean实例不一定是原来使用的那个有状态会话Bean实例,也有可能是一个新的有状态会话Bean实例,可是这个新的有状态会话Bean实例获得的会话状态正是被挂起的有状态会话Bean实例的会话状态。所以我上句话说的是“被挂起的会话状态”,读者朋友需要格外注意这点。

      具体的激活原理如下图所示:

计算机生成了可选文字:回业务接口,3:重新构建.Bean实例4:调用Bean实例,@POst内s、ivate。S:调用业务方法、汁粼酗团靳眺思个Bean料浪思舜晰t石司

图 2.2

      同无状态会话Bean一样,我们最后也附上一个有状态会话Bean的小Demo供大家理解。

      首先是EJB的服务器端:

/**
* @ClassName: 有状态会话Bean Demo实现类
*@Description: EJB服务器端实现类
*@author 孙丽端
* @date 2014年11月28日20:22:51
*/
package com.tgb.ejb;
 
public interfaceStatefulEjb {
publicvoid compute(int i);
publicint getResult();
}

/**
* @ClassName: 有状态会话Bean Demo实现类
*@Description: EJB服务器端实现类
*@author 孙丽端
* @date 2014年11月28日20:22:51
*/
package com.tgb.ejb;
 
importjavax.ejb.Remote;
importjavax.ejb.Stateful;
 
@Stateful
@Remote
public classStatefulEjbBean implements StatefulEjb {
 
privateint state;
 
@Override
publicvoid compute(int i) {
state= state +i;
 
}
 
@Override
publicint getResult() {
//TODO Auto-generated method stub
returnstate;
}
 
}

      其次是EJB的客户端调用代码实现:

/**
* @ClassName: 有状态会话Bean Demo客户端类
*@Description: EJB客户端类
*@author 孙丽端
* @date 2014年11月28日20:22:51
*/
package com.tgb.ejb;
 
importjavax.naming.InitialContext;
importjavax.naming.NamingException;
 
public classStatefulEjbClient {
publicstatic void main(String[] args) throws NamingException {
InitialContextcontext = new InitialContext();
 
StatefulEjbejb1 =(StatefulEjb)context.lookup("StatefulEjbBean/remote");
System.out.print(ejb1.getResult());                
ejb1.compute(1);
System.out.print(ejb1.getResult());                
ejb1.compute(1);
System.out.print(ejb1.getResult());        
 
StatefulEjbejb2 =(StatefulEjb)context.lookup("StatefulEjbBean/remote");
System.out.print(ejb2.getResult());                
ejb2.compute(1);
System.out.print(ejb2.getResult());                
ejb2.compute(1);
System.out.print(ejb2.getResult());                
 
}
 
}

 

     最后的运行结果是:

 

计算机生成了可选文字:里prob‘ems旦,。vodo。且坠吵。,‘on曰Conso‘e<terminated>StatefuIEjbClient[JavaApplication]C:\Java划D叭blnVavaw.exe(舀012012}一一

 

      通过对会话Bean的生命周期和两个子类型(有状态会话Bean和无状态会话Bean)的详细解说,不知道你明白了一些吗?

EJB初级篇--EJB组件之会话Bean