EJB初级篇--EJB组件之会话Bean
来源:程序员人生 发布时间:2015-01-16 08:07:34 阅读次数:3227次
上篇博文中我们已详解介绍了甚么是EJB。其实最简单的说:EJB就是运行在独立服务器上的组件,客户端是通过网络对EJB对象进行调用的。而我们常说的企业Bean组件可以分为3种类型:会话Bean、消息驱动Bean和实体Bean。根据利用设计的不同,开发者可以选择合适利用的组件类型。下面几篇博文中我会为大家分别详细的介绍这3种企业Bean组件。本篇博文则就先来介绍介绍会话Bean吧。
首先来介绍1下,甚么是会话Bean。会话Bean能够完成客户所要求的业务操作,它是含有业务逻辑的可重用组件,并能够用于业务进程。简单1句话:会话Bean就是用来实现业务逻辑的。
下面就详细介绍会话Bean的主要内容,包括以下两点:1是会话Bean的生命周期;2则是会话Bean的子类型。
-----------------------------------生 命 周 期-----------------------------------
先由1个例子引入:如果客户端代码调用用于完成“登录登记”的会话Bean,则EJB容器需要完成会话Bean组件实例的创建。在后续操作中,如果客户不再与该实例交互,利用服务器有可能会烧毁它。也就是说:会话Bean实例开始于客户取得其援用时,而终止于客户会话的终结。映照到会话Bean的生命周期,可以说:客户会话(Client
Session)的延续期就决定了使用中的会话Bean的存活期,也就是生命周期。而1般情况下,客户会话的延续期是比较短的,所以会话Bean的实例也是存活短暂的对象。
知道了会话Bean的生命周期后,那末操作会话Bean生命周期的又是甚么呢?答案就是EJB容器。不单单是会话Bean,EJB容器管理着EJB全部组件的生命周期。例如客户超时,EJB容器将会烧毁会话Bean实例。
-----------------------------------子 类 型--------------------------------------
会话Bean存在两种子类型:无状态会话Bean和有状态会话Bean,用于建模不同类型的会话。
1、无状态会话Bean
无状态会话Bean适用于只需单个要求会话便可完成的业务进程。这样,EJB组件不需要保护方法调用间的状态变更信息。
为了实现有效的Bean实例处理,EJB容器常常会使用实例池技术。下图是无状态会话Bean的实例池。我们可以清晰的导出无状态会话Bean的内部机制。
图1.1
由于无状态会话Bean不含会话状态,因此同1无状态会话Bean类的所有实例对客户而言都是等效的。而且无状态会话Bean不保存历史会话信息,所以它对调用其本身的客户也其实不关注。因此,任何无状态会话Bean都能够服务任何客户要求。由于这些无状态会话Bean都是1样的。
了解了原理以后,来1个很简单的小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());
}
}
最后的运行结果是:
2、有状态会话Bean
有状态会话Bean适用于需要若干要求构成才可完成的业务进程。这样,EJB组件就需要保护方法调用间的状态变更信息,最形象的就是淘宝购物车的状态了。在用户阅读商品到加入购物车直至购买,我们必须跟踪用户的状态,并且为单个客户保存状态信息。
图1.1是无状态会话Bean的实例池,EJB容器只需要在实例池中保护若干个Bean实例,便能服务大量的并发的客户。可是对有状态会话Bean来讲,这样是远远不够的。
在有状态会话Bean中各个Bean实例中存储的状态信息仅是单个客户的。如果和无状态会话Bean的处理1样,只是简单的将实例全部放置实例池中,当大量的并发客户操作时,内存中运行的有状态会话Bean实例就会过量而失去控制。
因此,为了限制内存中Bean实例的数量,EJB容器使用了挂起和激活两个操作。我们先来讲说挂起吧。
挂起是甚么呢?就和置之不理1样的,把它先保存起来,以后再用。在这里就是当有状态会话Bean实例暂时没有参与到客户要求中时,容器就有可能挂起它,它的会话状态会被安全的保存下来,而且其释放的内存可以供其他利用(EJB实例)使用。具体的挂起原理以下图所示:
图 2.1
这时候候读者朋友可能会问,那末EJB容器怎样知道该挂起那个Bean实例呢?上图中有提到,大部份容器使用最近最少使用的挂起策略,即简单的挂起最近没有使用到的有状态会话Bean实例。
1旦被挂起的有状态会话Bean实例的客户再次调用它,被挂起的会话状态将重新回到有状态会话Bean实例中。注意我说的是“被挂起的会话状态”,激活的有状态会话Bean实例不1定是原来使用的那个有状态会话Bean实例,也有多是1个新的有状态会话Bean实例,可是这个新的有状态会话Bean实例取得的会话状态正是被挂起的有状态会话Bean实例的会话状态。所以我上句话说的是“被挂起的会话状态”,读者朋友需要格外注意这点。
具体的激活原理以下图所示:
图 2.2
同无状态会话Bean1样,我们最后也附上1个有状态会话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());
}
}
最后的运行结果是:
通过对会话Bean的生命周期和两个子类型(有状态会话Bean和无状态会话Bean)的详细解说,不知道你明白了1些吗?
生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠