EJB概述

来源:互联网 发布:羊毛大衣 知乎 编辑:程序博客网 时间:2024/04/30 05:25

Enterprise JavaBean(EJB)是一种服务器端组件的规范。EJB规范的目标是定义一个标准,以创建可参与分布式的、面向对象的应用组件。javaBean定义了应用程序组件的一个标准接口,同样,EJB定义了服务器端组件的标准。通过EJB,java开发者将能够通过集成定义良好的组件来更快地开发分布式应用。

制定EJB规范的动机就是使编写具有网络功能的应用程序更容易。反过来这就要求应用程序有一个定义其各种组件的简易办法。JavaBean是定义客户端组件的标准,EJB是定义服务器端组件的标准。一些大型的多层应用可以在客户端使用JavaBean,在服务端使用EJB。

EJB生态环境(角色)

开发者:创建EJB的程序员

装配者:使用EJB的程序员

部署者:部署者是定义Bean环境并把Bean部署到特定的宿主服务器上的人。

服务器提供商:

容器提供商:容器就是实际上的服务提供者,而服务器仅仅是容器的宿主机。

管理员

创建EJB的方法

创建EJB是一个分为几步的过程。这个过程由通常EJB是通过网络被访问的这一事实所影响。

先看下以部署的Bean应用的基本结构:

第一,EJB和调用它的客户端可以存在,也可以不存在于同一个应用中。

第二,客户端通过一个实现了EJBHome接口的对象来访问EJB。这个对象扮演着一个EJB工厂角色,它为客户端创建EJB,并在客户端的工作完成后为其删除相应的EJB。

第三,客户端通过一个远程接口访问EJB。实现这一接口的对象是EJB宿主服务器在部署过程中构造的。最后,这个接口或者说是代理,把消息转发给相应的EJB。

为EJB通过EJBHome和EJBObject对象是容器的职责。为了深入理解这个结构,让我们研究一下EJB宿主服务器可能提供的两个服务。首先,宿主服务器会支持EJB的缓存池。例如:如果客户端不必在每个请求中都与同一个Bean交互,那么服务器就可以为所有的客户端维护一个Bean的缓存池,从而降低被使用的自源的总数。缓冲池的工作由EJBHome完成,它只创建必要数量的Bean,而代理只在需要时才从缓冲池获取一个Bean。另一个服务是基本的持久性机制。EJBHome为那些不得不从数据库或其他持久性的数据源加载数据的Bean提供了一个简单的接口,搜有的持久性都可以在EJBHome或容器中实现。

那么程序员都要作什么呢?

    1)定义远程接口

    2)定义EJBHome接口

    3)定义EJB

    4)创建所需要的任何附加的类

    5)定义必要的部署信息

    6)编译Bean

    7)为部署而把Bean打包

    8)部署Bean

在使用消息驱动Bean时,客户端与服务器上Bean的耦合通过JMS接口降低了。因此,消息驱动Bean不需要EJBHome或远程接口。取而代之的时Bean和客户端使用相同的消息格式和JMS目标地址。

定义远程接口

在这一步中,虽然应用的设计者有许多工作要做,但对于程序员来说,这可能是最容易的一步。远程(Remote)接口是从Remote和EJBObject派生来的一个标准Java接口。远程接口在包java.rmi中定义并且没有定义任何方法。这是一种类型机制,它告送系统实现远程接口的对象实际上是一个可以通过实际上是一个可以通过RMI或RMI- IIOP被远程访问的对象。另一方面,EJBObject在包javax.ejb中定义,它拥有的方法最终在部署过程中由EJB宿主服务器的代理对象实现。这些方法是宿主服务器实现规范的代码中的一层。

一个定义远程接口的示例:

package stateless;import javax.ejb.*;import java.rmi.RemoteException;import java.Remote;public interface StatelessId extends EJBObject, Remote{    public int getId() throws RemoteException;}

注意:在远程接口中声名的所有方法都必须声名抛出RemoteException异常。可能抛出RemoteException异常使得EJB和所有的java分布式计算缺乏透明度。尽管这个通用的异常类型把网络计算的各种危险缩小为一个概念,但是对于那些不基于分布式计算编程技术的程序来说,它仍是无用的。换言之,我们不能忘记EJB不是本地程序的一部分,因为它们有时会抛出RemoteException异常。

这一步最容易的就是写接口,最难的是为分布式应用做设计。这可能是一个乏味的过程,但是只要我们有了设计,就可以把它变成一个java的接口,即远程接口。

在接口中定义的输入参数和返回值应该是RMI-IIOP安全的,这将确保这些数据被更广泛的传输机制所支持。

定义本地接口

为EJB创建EJBHome接口既简单又复杂。说它简单是因为我们只需要实现一个EJBHome派生的接口。这个接口定义了四个方法,但是这些方法中没有定义如何创建Bean和如何访问Bean。这就麻烦的地方。实际上sun为了最大化灵活性,用一个代码约定来规范EJB的工厂方法,这个代码约定规定一个EJBHome接口必须为Bean做如下事情:

  • 提供名为create的方法,方法的参数由应用来决定。
  • 所有的create方法的返回值类型都应为远程接口。
  • 每个create方法都要声名两个异常:CreateException和RemoteException
  • 只使用RMI标准中允许的类型做参数。

给定了这些指定方针,我们就可以定义任意数量的create方法了,服务器用这些方法来创建EJB实例。我们定义的create方法由客户端调用,以在服务器创建和访问EJB。这就意味着在定义create方法时,要思考客户端需要得到什么。

我们看下本地接口定义的示例:

package staeless;import javax.ejb.*;import java.rmi.remoteException;public interface StatelessIdHome extends EJBHome{    StatelessId create() throws CreateException,RemoteException;}

定义EJB

定义EJB的第一步是定义它的类型信息,类型信息在超类和被实现的接口中定义。一般的Bean简单从Object类派生出来的,显然它不是我们要的类型信息。所以,所有的EJB都必须实现javax.ejb.EnterpriseBean接口。这个接口恰恰就是用于标识类型,没有提供任何方法。

Bean还必须实现下面三个接口中的一个:EntityBean、SessionBean或者MessageDrivenBean。这些接口实际上是从EnterpriseBean派生来的。

定义会话Bean或实体Bean的第二步是定义与EJBHome接口中的create方法相对应的方法。对该接口接口中的每一个create方法,EJB中必须有一个名为ejbCreate的方法与之相对应,ejbCreate方法必须与home中对应create方法有完全相同的参数。ejbCreate声名抛出的异常,create方法也必须声名抛出同样类型的异常。然而,ejbCreate方法不需要声名它要抛出RemoteException异常。

最后一步就是实现已经在远程接口中定义的方法和其他Bean需要的方法,这是编程工作的主体内容。整个EJB规范就是为了让我们把注意力集中在这一步而设计的。

package statelessid;import javax.ejb.*;import java.io.serializable;import java.util.*;public class StatelessIDBean implements SessionBean{    protected SessionContext context;    protected int id;    protected static int nextId = 0;    public static int nextId()    {        return (nextId++);    }    public void ejbActivate()    {      }    public void ejbRemove()    {     }    public void ejbPassivate()    {    }    public void setSessionContext(SessionContext ctx)    {        context = ctx;    }        public void ejbCreate()    {         id = nextId();    }    public int getId()    {         try         {             Thread.sleep(1000);         }         catch(Exception exp)         {         }    }}

通常EJB开发者应该遵守以下编程规则:

  • Bean不能创建线程或者结束正在运行的线程。
  • Bean不能使用可变的静态变量,为了安全,EJB中所有静态变量都必须标以final。
  • Bean中不能使用线程的同步原语,即不能有synchronized的代码段或方法,因为这回影响宿主服务器的线程管理
  • 一个Bean除非特定声明它要管理事务,否则它就不能做任何事务管理的工作。
  • 每个Bean都会被分配一个安全标识,不要企图改变这个标识。
  • 依赖容器进行事务管理的Bean不能管理JDBC事务;容器将会为它们进行这些操作。

创建所需的附加类

定义必要的部署信息

编译Bean

为部署而打包Bean

部署Bean

 

原创粉丝点击