302班

java突击队
posts - 151, comments - 74, trackbacks - 0, articles - 14
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

EJB介绍

Posted on 2007-06-19 18:36 停留的风 阅读(342) 评论(0)  编辑  收藏 所属分类: 快速前进的Java

EJB

1.EJB体系结构:
     包括客户端、服务器端。
     客户端:包含了调用EJB组件特定业务所需的EJB接口(包括本地和远程EJB接口);服务器端处理对象的句柄。
     服务器端:包含了EJB组件实现的实例;用来在客户端和EJB组件之间进行映射的容器代码。
     EJB客户应用程序使用JNDI来查找对本地接口的实例引用,通过EJB接口来调用和引用EJB组件的全部方法和属性。
2.开发EJB程序的步骤:

     开发主接口、开发组件接口、开发Bean实现类、编写部署文件。

     开发主接口:bean的主接口程序,命名为<bean-name>Home,继承EJBHome,负责bean的生命周期(生成、删除、查找bean)。只需提供主接口,类方法的实现由容器完成。其方法有create,remove,search等。

     开发组件接口:命名为<bean_name>,继承EJBObject,当远程用户调用主接口方法create时,得到一个组件的远程引用,为这个bean的所有方法提供一个接口类,类和主接口的实现是由容器在部署时自动生成。

     开发Bean的实现类:命名为<bean_name>EJB,实现SessionBean接口。实现ejbCreate、ejbRemove等。

     编写部署文件:完整的bean由java类和描述其特性的ejb-jar.xml文件组成,将其打包,放在jboss中的deploy文件夹中。

3.开发和部署测试程序:

     开发一个Servlet测试程序,将测试程序放在tomcat的webapps中。

4.会话Bean:

     分为有状态会话Bean和无状态会话Bean。EJB容器通过ejb-jar.xml来判断是否为一个SessionBean提供保存状态的服务。

所有SessionBean的寿命周期由容器控制,Bean的客户不拥有Bean的直接引用。部署一个EJB时,容器为这个Bean分配几个实例到Component Pooling,当客户请求一个Bean时,J2EE服务器将一个预先实例化的Bean分配出去,在客户的一次会话中,可以只引用一次Bean,就可以执行这个Bean的多个方法。如果另一个客户请求同一个Bean,容器检查池中空闲的Bean(不在方法和事务中,如果一个客户长时间引用一个Bean,单执行一个方法后需等待一段事件执行另一个方法,则这段时间也是空闲的),如果全部的实例都已用完,则会自动生成一个新的实例放在池中,并分配给请求者。当负载减少时,池会自动管理Bean实例的数量,将多余的实例从池中释放。

5.有状态会话Bean:

     在客户访问之间保存数据,在客户引用期间维护Bean中的所有实例数据的状态值。

     有四种状态:不存在、方法现成、事务中方法现成、钝化。

     不存在:有状态SessionBean的初始化状态为不存在,当客户引用一个Bean时,按照下图中初始化一个Bean。    方法现成:如果客户调用remove()方法回到不存在状态,并触发Bean的ejbRemove()方法。如果客户长时间不调用Bean或服务器准备释放一些内存资源,则容器调用ejbPassivate()将这些Bean从组件池中钝化,此时释放分配的资源。当请求被钝化的Bean时,容器调用ejbActivate()激活Bean,Bean转到方法现成状态时分配Bean所需的资源。

     Bean本身可以管理事务(BMT Bean-Managed Transactions),也可由容器管理事务(CMT Container-Managed Transactions)。对于CMT,容器在方法开始时打开事务,在方法结束时实现事务。通过afterBegin()、beforeCompletion()、afterCompletion()来获取事务的各个状态,afterCompletion(true)表示事务完成,afterCompletion(false)表示事务被撤消。 

     setSessionContext()将对象的语境放到对象变量中,容器在结束会话Bean或自动超时死亡之前自动调用ejbRemove()方法,此方法中可以用来释放资源,

6.无状态会话Bean:

     不会在客户访问之间保存数据,不能申明实例变量,方法只能操作传来的参数。

如果数据是数据的瞬像,则用无状态会话Bean。弊端:本该存储在服务器端的数据被保存在客户中,每次调用这些数据要以参数的方式传递给Bean。如果数据状态非常敏感,则不要使用无状态会话Bean。

有两种状态:存在、不存在。


只对客户提供业务逻辑,服务器端不保存客户端的任何数据状态,这些状态被保存在客户端。

当客户端不存在一个无状态Session Bean时,通过远程主接口的create()方法创建一个Bean,newInstance()负责实例化Bean,ejb容器调用bean类的setSessionContext()方法把运行环境对象SessionContext传递给Bean,然后调用ejbCreate()方法进行初始化和资源分配。

7.Jboss:

     用Jboss来运行EJB,将EJB的.jar文件放在jboss deploy文件夹中。这个jboss版本是Jboss2.2.1。将该EJB所有的class文件放在tomcat的webapps中。

配置ejb-jar.xml文件:

     <?xml version="1.0" encoding="UTF-8"?>

<ejb-jar>

          <description>This is Hello Ejb</description>

          <display-name>HelloBean</display-name>

          <enterprise-beans>

              <session>

                   <ejb-name>Hello</ejb-name>

                   <home>hello.HelloHome</home>

                   <remote>hello.Hello</remote>

                   <ejb-class>hello.HelloEJB</ejb-class>

                   <session-type>Stateless</session-type>

                   <transaction-type>Container</transaction-type>

              </session>

          </enterprise-beans>

</ejb-jar>

ejb-name——是EJB的接口类名称。这里的接口类是Hello。

home ——是主接口,包括完整的包名。

ejb-class ——是EJB的类实例,包括完整的包名。

remote ——是EJB的接口类名称,包括完整的包名。

session-type——有两个值Stateless、Stateful。

8.实体Bean:

     用来代表底层的对象,常用来映射关系数据库中的纪录。关系数据库的字段可以被一对一的映射到一个Entity Bean中,表之间的关系可以看成是Entity Bean之间的关系,一个Entity Bean实例可能会对应表中的一条纪录或一个查询结果。

     持久性:数据库纪录的任何改变也应该被同步组件池中相关的Bean中。这一过程是持久性,是Entity Bean最重要的特征。可分为:容器管理持久性(CMP Container-Managed Persistence)和Bean管理持久性(BMP Bean-Managed Persistence)。

     容器管理者:是在Bean与基础数据库表纪录值之间负责同步工作的操作者。CMP Bean的持久性由EJB容器负责,与数据库的操作在部署EJB时由EJB部署者描述,由容器实现SQL操作和同步工作。BMP Bean的持久性由Bean负责,由Bean开发者负责与数据库交互的代码部分。

9.EJB 1.1规范中的CMP:

     用CMP方式编写的Bean对于数据库的操作是在部署时由部署者映射到实际的数据库字段,这样增强程序的移植性。不必考虑CMP Bean如何连接到数据库,者在部署Bean时由部署者为CMP Bean指定一个数据库连接池的JNDI名。

     在设计一个CMP Bean时,Bean被固定映射一个实体表,表中的每个指定字段被映射成Bean的一个public 型类变量,在实际开发中,只需在Bean的实现类中,申明这些变量,映射操作和SQL处理由部署者和容器自动完成。

     只有Entity Bean有主键,每个Entity Bean的实例代表一行纪录。主键类型一般对应于数据表主关键字类型。在Bean的实现类中ejbCreate(),CMP Bean返回一个NULL类型的值,BMP Bean返回一个主键类型对象;在Bean的远程主接口中,create()用来插入一条数据,并根据ejbCreate()返回一个Bean的引用。

     CMP Bean和会话Bean一样需要设计:远程主接口、组件接口和Bean的实现类。

10.Entity Bean的寿命周期: 
     客户在调用完一个Entity Bean且释放资源后,Entity Bean的实例仍然存在于组件池中,与映射的数据库纪录保持持久性。

     Entity Bean的开始状态为不存在,不引用,当客户直接向数据库插入纪录后,新的纪录将被映射Bean的实例放到组件池中等待引用,状态为存在,不引用,可以通过主接口的find方法查找这些对象到存在、引用状态,也可通过Home.remove()将其删除,回到初始状态。在初始状态通过Home.create()可以到存在、引用状态,引用的句柄由create方法返回。只有在存在、引用时可以调用组件的业务方法。用set null可以将存在、引用状态的Bean释放资源,使用主接口和组件接口的remove()将删除被映射的数据纪录,释放Entity Bean资源,但引用资源仍未释放,只用set null才可以释放引用资源。当数据库纪录被其他应用程序或进程直接插入数据后,容器将自动维持其持久性,在客户端执行完一个Entity Bean后,一定要释放其引用的资源。  

     当远程客户调用远程主接口的create()时,容器调用newInstance()来创建一个Bean实例,调用setEntityContext()将当前的情境传递给Bean,进入池共享阶段。调用ejbCreate()、ejbPostCreate()来完全初始化Bean并进入准备阶段,进入准备阶段的Bean业务逻辑方法可以被客户调用,在调用setxx或getXx时,容器(CMP)或Bean(BMP)会多次调用更新(ejbStore())和提取(ejbLoad())来维护组件的持久性。

11.开发CMP Bean:

     开发主接口:继承EJBHome, 开发组件接口:继承EJBObject,组件接口中申明的方法必须在Bean类中实现,组件的主键有默认的操作方法,所以可以不用在组件接口中申明,使用getPrimary()可以获取组件的主键,返回一个Object类型,在客户端程序中通过上溯造型成合适的类型。

     开发Bean的实现类:实现了EntityBean接口,ejbLoad()从数据库中读取数据纪录,ejbStore()提交当前数据状态到纪录,ejbRemove()释放实例对象并删除相关映射的数据纪录,setEntityContext()使当前Bean实例访问Bean情境,unsetEntityContext()释放特定的情境资源。Entity Bean激活时的调用顺序:ejbActivate()—ejbLoad();钝化时的顺序:ejbStore()—ejbPassivate();对于CMP的ejbCreate()返回为主关键字类型,由于容器来实现,在此方法中只需关联相关的映射字段,然后返回null。必须在类中定义与数据库表相关联的映射字段。

     编写部署文件:部署文件是ejb-jar.xml。

     对于CMP Bean来说,当一个Bean实例被客户引用,容器会自动读取Bean的实例字段,然后,通过容器与数据库发生关系,保存改变的数据,执行完后Bean被钝化,并调用ejbPassivate()来通知Bean。然后又调用这个Bean时,Bean先调用ejbActivate()通知Bean,Bean实例要激活,然后从数据库中提取数据,并自动将数据值映射到Bean的实例,然后调用ejbLoad(),实例再一次被初始化,最后才开始执行要执行的业务方法。

12.开发BMP Bean:

     当一个Bean实例被客户引用,并执行一个业务方法后,容器执行ejbStore(),由这个方法把数据保存在数据库中,执行完后Bean被钝化,调用ejbPassivate()通知Bean。当客户又调用这个Bean的某业务方法时,被钝化的Bean又重新激活,EJB对象先调用ejbActivate()通知Bean,Bean实例要激活,然后调用Bean的ejbLoad(),此方法负责从数据库中提取数据,Bean实例被初始化,最后才执行要执行的业务方法。

     要求所有的数据库操作由Bean实例完成。

     setXxx():来设置字段的值;getXxx():来获取Bean字段的值;ejbCreate():由开发者实现,返回创建纪录的主键值;ejbLoad():以实现组件非持久性状态缓存持久性信息;ejbStore():将信息从组件的非持久性状态转到持久性状态;ejbRemove():必须由开发者实现;unsetEntityContext():释放在setEntityContext()中缓存的情境资源和取得的资源;setEntityContext():设置情境资源,初始化数据库连接对象;ejbActivate():通过情境参数设置主键值;ejbPassivate():取消Bean与数据库记录的持久性工作,进入钝化状态。

     开发主接口:与开发CMP Bean的主接口一样。

     开发组件接口:与开发CMP Bean的主件接口一样。

     开发Bean的实现类:Bean不在声明全局的类变量,类变量的映射改教给Bean来管理。需要声明一个EntityContext情境变量,通过这个变量的getPrimaryKey()得到保存在情境中的主关键字,以便在Bean激活时重新初始化Bean的数据。因为要对数据库直接操作,所以定义一个DataSource的对象,在Bean初始化从连接池中取得一个有效数据库的对象。定义的Connect对象将在获取一个数据库连接时被引用。定义一个String类型的static变量存放一个获得数据库资源的JNDI名。


只有注册用户登录后才能发表评论。


网站导航: