在《
EJB组件:基本结构解析》中,我们已经详细介绍了EJB组件的Home接口、Remote接口以及EJB组件类等内容。今天,我们将分析EJB的会话组件应用及分类。
会话组件的应用方式
会话类型EJB组件是一种客户端应用程序通过EJB组件的Home接口创建并对客户端连接专有的组件类型,通常在EJB服务器中创建的会话组件对象实例不与其它客户端应用共享。一个会话组件往往实现一个商务过程、简单的计算过程或逻辑处理过程,在应用过程中客户端的会话角色不会发生变化。
例如,在网上购物的电子商务应用中,客户在浏览购物之前创建一个购物车,这个购物车的功能可由一个会话类型组件来完成。客户在购物过程中购物车的属主为创建购物车的客户,其它客户不能向不属于自己的购物车中添加商品。在客户结账完成一次购物之后将扮演购物车角色的会话组件从EJB容器的实例池中删除,结束一次会话过程。
会话类型的EJB组件在分布式多层应用系统中通常有两种类型的应用方式:
三层体系结构中的应用方式
在常规三层体系结构的分布式应用中,通过将处理商务逻辑的代码封装为部署在EJB服务器中的EJB组件、将系统的显示逻辑部署在客户端,使得整个系统结构更加清晰,如下图所示。
图1 三层结构分布式应用中会话类型EJB组件部署图
在上图所示的EJB服务器中部署了多个EJB组件对象。就会话类型EJB组件而言,其主要作用在于根据客户端应用提出的服务请求进行商务逻辑处理并可以与部署在应用系统后台的数据库进行交互。会话类型EJB组件与数据库的交互是通过JDBC等Java语言数据库访问方式实现的,而不是象实体类型EJB组件那样组件本身表示的是数据库表中的记录。
基于WEB分布式应用中的应用方式
会话组件基于WEB的分布式应用方式中,客户端浏览器利用HTTP协议以超文本的方式与部署在WEB服务器中的WEB组件进行交互。在WEB组件中封装了JSP或者Servlet等超文本页面的动态生成代码,用于根据商务逻辑的处理情况动态地创建客户端浏览器中显示的页面内容。会话类型EJB组件基于WEB应用的方式如下图所示:
图2 WEB应用方式中会话类型EJB组件部署图
在基于WEB的分布式应用中,可以将商务逻辑处理部分的代码直接编写为WEB服务器中WEB组件的代码。但是,将商务规则代码封装成为EJB组件,使得不同类型的客户端应用能够共享部署在EJB服务器中的组件对象,提高了代码的可重用性和可移植性。
会话组件的继承关系
会话类型EJB组件的定义实现SessionBean接口对象。该接口的定义如下面代码所示:
<ccid_nobr></ccid_nobr>
在上面的SessionBean接口定义中,EnterpriseBean接口是一个空的接口定义,作为会话类型EJB组件和实体类型EJB组件共同的父接口。SessionBean接口继承EnterpriseBean接口。
会话类型EJB组件的激活和关闭
为了提高EJB服务器的工作效率,减少EJB组件对服务器资源的消耗,EJB规范定义了会话类型EJB组件的激活和关闭机制,用于动态调整EJB容器的组件实例池中活动EJB组件实例对象的数量和状态。
EJB服务器调整组件实例状态的方法为:在EJB容器的属性中包括一个会话类型EJB组件处于非活动状态的时间阙值属性。该时间属性由EJB组件的部署者根据应用系统的组件数量和EJB服务器的性能来进行设置。当某个EJB组件对象实例处于不活动状态的时间达到这个时间界限时,EJB容器就把这个EJB组件实例拷贝到二级存储设备中并从实例池中删除组件实例,同时释放这个EJB组件占用和引用的系统资源。如果EJB组件中的某个方法是正在运行事务中的一部分,那么不能将该EJB组件实例的激活状态转换关闭状态。
当客户端应用调用会话类型EJB组件中的方法时,如果该EJB组件实例处于关闭状态,则EJB容器重新激活该组件对象,在EJB容器中创建该组件的实例用于响应客户端的调用请求。由于无状态会话类型EJB组件不维护任何客户端状态,因而没有必要保存组件中包含的客户端信息,EJB容器可以直接将达到非活动状态时间阙值的EJB组件从EJB容器中删除。由于这些状态转换由EJB服务器来完成,因而客户端不会感觉到EJB组件实例的状态变化。
相应地,在SessionBean接口中定义了ejbActivate方法和ejbPassivate方法,用于EJB容器调用该方法对EJB组件的状态进行转换。这样,通过SessionBean接口中定义的控制EJB组件状态的方法,可以控制一段时间内EJB组件实例的数量和状态,极大程度地提高了EJB服务器的工作效率,减少EJB组件对服务器端资源的消耗。
会话类型EJB组件的分类
根据是否维护客户端应用在EJB服务器中的状态,可以将会话类型EJB组件分为有状态(Stateful)和无状态(Stateless)两种类型。
有状态会话类型EJB组件
有状态会话类型EJB组件实例与创建EJB组件的客户端应用之间存在着一一对应的关系,EJB容器代理客户端应用对有状态会话类型EJB组件实例中方法的调用。客户端应用与EJB容器中有状态会话类型EJB组件实例之间的对应关系如下图所示:
图3 客户端应用与有状态会话类型EJB组件实例之间对应关系图
由上图可以看出:客户端创建EJB组件对象实例获得EJBObject类型对象。当客户端调用该组件对象实例中的商务方法时,EJB容器由组件的RMI类型对象实例作为远程调用代理与实例池中的有状态会话类型EJB组件实例进行交互,从而调用EJB组件中定义的方法。针对EJB容器中定义的每一个有状态会话类型EJB组件,EJB容器均创建一个RMI类型的远程对象作为EJB组件与客户端之间的代理。
无状态会话类型EJB组件
无状态会话类型EJB组件在客户端调用组件的方法期间不维护任何客户端的状态信息。EJB容器将所有创建的无状态会话类型EJB组件实例均维护在一个组件实例池中,客户端对于同一EJB组件的调用过程均可以由同一个EJB组件对象实例来完成。客户端应用与EJB容器中无状态会话类型EJB组件对象实例之间的对应关系如下图所示:
图4 客户端应用与无状态会话类型EJB组件实例之间对应关系图
由上图可以看出:所有的客户端应用在调用部署在EJB服务器中的无状态会话类型EJB组件的方法时,均利用同一个RMI类型远程对象作为EJB组件的调用代理。
无状态会话类型EJB组件可以在不同的客户端应用之间共享。但共享的过程是某一时刻只能有一个客户端应用调用EJB组件中的同一方法。由于EJB组件不需要维护客户端应用的状态,因此客户端调用任何无状态会话类型EJB组件实例中的同一方法均能够获取相同的服务,这使得EJB容器可以维护一个较小的EJB组件实例池,节省对服务器资源的消耗。
在了解了EJB的会话组件之后,我们将介绍EJB组件的无状态会话类型,请您继续关注开发者频道。
会话类型EJB组件是一种客户端应用程序通过EJB组件的Home接口创建并对客户端连接专有的组件类型,通常在EJB服务器中创建的会话组件对象实例不与其它客户端应用共享。一个会话组件往往实现一个商务过程、简单的计算过程或逻辑处理过程,在应用过程中客户端的会话角色不会发生变化。
例如,在网上购物的电子商务应用中,客户在浏览购物之前创建一个购物车,这个购物车的功能可由一个会话类型组件来完成。客户在购物过程中购物车的属主为创建购物车的客户,其它客户不能向不属于自己的购物车中添加商品。在客户结账完成一次购物之后将扮演购物车角色的会话组件从EJB容器的实例池中删除,结束一次会话过程。
会话类型的EJB组件在分布式多层应用系统中通常有两种类型的应用方式:
三层体系结构中的应用方式
在常规三层体系结构的分布式应用中,通过将处理商务逻辑的代码封装为部署在EJB服务器中的EJB组件、将系统的显示逻辑部署在客户端,使得整个系统结构更加清晰,如下图所示。
![44328.jpg](http://developer.ccidnet.com/pub/attachment/2002/12/44328.jpg)
在上图所示的EJB服务器中部署了多个EJB组件对象。就会话类型EJB组件而言,其主要作用在于根据客户端应用提出的服务请求进行商务逻辑处理并可以与部署在应用系统后台的数据库进行交互。会话类型EJB组件与数据库的交互是通过JDBC等Java语言数据库访问方式实现的,而不是象实体类型EJB组件那样组件本身表示的是数据库表中的记录。
基于WEB分布式应用中的应用方式
会话组件基于WEB的分布式应用方式中,客户端浏览器利用HTTP协议以超文本的方式与部署在WEB服务器中的WEB组件进行交互。在WEB组件中封装了JSP或者Servlet等超文本页面的动态生成代码,用于根据商务逻辑的处理情况动态地创建客户端浏览器中显示的页面内容。会话类型EJB组件基于WEB应用的方式如下图所示:
![44329.jpg](http://developer.ccidnet.com/pub/attachment/2002/12/44329.jpg)
在基于WEB的分布式应用中,可以将商务逻辑处理部分的代码直接编写为WEB服务器中WEB组件的代码。但是,将商务规则代码封装成为EJB组件,使得不同类型的客户端应用能够共享部署在EJB服务器中的组件对象,提高了代码的可重用性和可移植性。
会话类型EJB组件的定义实现SessionBean接口对象。该接口的定义如下面代码所示:
<ccid_nobr></ccid_nobr>
<ccid_code>public interface javax.ejb.SessionBean extends javax.ejb.EnterpriseBean { public void ejbActivate() throws RemoteException; public void ejbPassivate() throws RemoteException; public void ejbRemove() throws RemoteException; public void setSessionContext(SessionContext context) throws RemoteException; }</ccid_code>
在上面的SessionBean接口定义中,EnterpriseBean接口是一个空的接口定义,作为会话类型EJB组件和实体类型EJB组件共同的父接口。SessionBean接口继承EnterpriseBean接口。
为了提高EJB服务器的工作效率,减少EJB组件对服务器资源的消耗,EJB规范定义了会话类型EJB组件的激活和关闭机制,用于动态调整EJB容器的组件实例池中活动EJB组件实例对象的数量和状态。
EJB服务器调整组件实例状态的方法为:在EJB容器的属性中包括一个会话类型EJB组件处于非活动状态的时间阙值属性。该时间属性由EJB组件的部署者根据应用系统的组件数量和EJB服务器的性能来进行设置。当某个EJB组件对象实例处于不活动状态的时间达到这个时间界限时,EJB容器就把这个EJB组件实例拷贝到二级存储设备中并从实例池中删除组件实例,同时释放这个EJB组件占用和引用的系统资源。如果EJB组件中的某个方法是正在运行事务中的一部分,那么不能将该EJB组件实例的激活状态转换关闭状态。
当客户端应用调用会话类型EJB组件中的方法时,如果该EJB组件实例处于关闭状态,则EJB容器重新激活该组件对象,在EJB容器中创建该组件的实例用于响应客户端的调用请求。由于无状态会话类型EJB组件不维护任何客户端状态,因而没有必要保存组件中包含的客户端信息,EJB容器可以直接将达到非活动状态时间阙值的EJB组件从EJB容器中删除。由于这些状态转换由EJB服务器来完成,因而客户端不会感觉到EJB组件实例的状态变化。
相应地,在SessionBean接口中定义了ejbActivate方法和ejbPassivate方法,用于EJB容器调用该方法对EJB组件的状态进行转换。这样,通过SessionBean接口中定义的控制EJB组件状态的方法,可以控制一段时间内EJB组件实例的数量和状态,极大程度地提高了EJB服务器的工作效率,减少EJB组件对服务器端资源的消耗。
根据是否维护客户端应用在EJB服务器中的状态,可以将会话类型EJB组件分为有状态(Stateful)和无状态(Stateless)两种类型。
有状态会话类型EJB组件
有状态会话类型EJB组件实例与创建EJB组件的客户端应用之间存在着一一对应的关系,EJB容器代理客户端应用对有状态会话类型EJB组件实例中方法的调用。客户端应用与EJB容器中有状态会话类型EJB组件实例之间的对应关系如下图所示:
![44330.jpg](http://developer.ccidnet.com/pub/attachment/2002/12/44330.jpg)
由上图可以看出:客户端创建EJB组件对象实例获得EJBObject类型对象。当客户端调用该组件对象实例中的商务方法时,EJB容器由组件的RMI类型对象实例作为远程调用代理与实例池中的有状态会话类型EJB组件实例进行交互,从而调用EJB组件中定义的方法。针对EJB容器中定义的每一个有状态会话类型EJB组件,EJB容器均创建一个RMI类型的远程对象作为EJB组件与客户端之间的代理。
无状态会话类型EJB组件
无状态会话类型EJB组件在客户端调用组件的方法期间不维护任何客户端的状态信息。EJB容器将所有创建的无状态会话类型EJB组件实例均维护在一个组件实例池中,客户端对于同一EJB组件的调用过程均可以由同一个EJB组件对象实例来完成。客户端应用与EJB容器中无状态会话类型EJB组件对象实例之间的对应关系如下图所示:
![44331.jpg](http://developer.ccidnet.com/pub/attachment/2002/12/44331.jpg)
由上图可以看出:所有的客户端应用在调用部署在EJB服务器中的无状态会话类型EJB组件的方法时,均利用同一个RMI类型远程对象作为EJB组件的调用代理。
无状态会话类型EJB组件可以在不同的客户端应用之间共享。但共享的过程是某一时刻只能有一个客户端应用调用EJB组件中的同一方法。由于EJB组件不需要维护客户端应用的状态,因此客户端调用任何无状态会话类型EJB组件实例中的同一方法均能够获取相同的服务,这使得EJB容器可以维护一个较小的EJB组件实例池,节省对服务器资源的消耗。
在了解了EJB的会话组件之后,我们将介绍EJB组件的无状态会话类型,请您继续关注开发者频道。