您的位置:首页 > 其它

J2EE学习笔记:第五天 EJB

2011-06-13 00:29 204 查看
(内容安排较乱 , 仅作本人个人学习笔记)
1 EJB概述
EJB实际上是一个被管理的组件,存在于J2EE容器中,由J2EE容器负责创建,控制,销毁,并控制当前存在的EJB数量和EJB所用的资源(内存和数据库连接等)。
每个容器维护一个分配给客户端的EJB实例池,当客户端不再需要EJB时,该实例将会被返回到EJB实例池中,并释放其资源,而在负载过重的情况下,即使客户端在使用EJB,EJB实例也会被容器强制返回实例池,但是这个实例还可以给其他客户端使用,而当客户端向EJB发起另一个请求时,容器会重新建立初始EJB实例来响应这个请求,也就是说一些EJB实例和他们所使用的资源可以在多个客户端之间进行共享。
EJB使用容器提供的服务(并将其服务以RMI远程接口的形式导出),如自动安全性,自动事务,声明周期管理等,EJB必须实现 允许容器管理组件的接口,从而可以使用这些服务。EJB被打包在配置信息中,配置信息声明了组件的需求,容器就代表组件使用这些信息来执行认证和控制事务。

2 EJB类型
(1)会话EJB
用于映射业务过程流,它由两种子类型,即无状态会话EJB和有状态会话EJB
(2)实体EJB
用于映射数据组合和相关联的功能,它通常基于底层的数据存储集,并基于存储集中的数据模式进行创建
(3)消息驱动EJB
它在概念上类似于会话EJB,但只有当异步消息到达时才被激活

3 EJB隐藏了程序的复杂性,从UI和数据访问中分离业务逻辑,帮助开发人员专注于业务代码的编写:
(1)每个bean都遵循一个定义的生命周期和一套规则,这样在系统代码和应用程序代码之间提供了一个明显的分界线
(2)声明属性允许开发人员无需编写代码控制这些功能即可指定组件的事务行为
(3)可部署的J2EE应用程序提供的部署信息描述了多个EJB之间的关系,同时定义了EJB需要的资源。
例如 当我们用swing来开发应用时,如果底层的业务功能使用EJB实现,那么我们不需要重新开发整个应用程序就可以用另一个不同的展示层来替代swing。



而且要注意,如果要使用EJB实现分布式应用程序,那么要明确用户接口和底层业务逻辑,在用户接口和业务逻辑混合的情况下,不适合使用EJB

4 容器提供给EJB的服务
(1)通过代理实现分发—容器为EJB生成客户端桩和服务器端骨架,桩和骨架使用基于I IOP协议的RMI进行通信。
(2)生命周期管理 – Bean的初始化,状态管理,销毁都由容器驱动
(3)命名与注册 – EJB容器和服务器为EJB提供了堆命名服务的访问,远程和本地客户端使用这些命名服务查找EJB,EJB本身使用这些命名服务查找自己所需要的资源
(4)事务管理 – 开发者可以将事务的创建和控制任务 委派给 容器来实现
(5)安全性和访问控制 – 开发者将执行安全的任务 委派给 容器来实现
(6)持久性 – 利用实体EJB的容器管理的持久性机制,可以存储和恢复状态。

5 EJB开发者要定义或派生bean需要的业务操作,并在RMI远程接口中对这些操作进行正式化。远程接口的定义需要遵循一些规则:



当使用RMI远程方法时,连续对象(实现Serializable接口)通过值进行传递,然而远程对象(EJB)通过引用进行传递。通过值进行传递意味着发送一个对象副本。这有以下几层含义:首先,连续对象(在远程接口上传递)的用户不再共享同一个对象; 其次,通过bean的远程接口调用方法时可能会降低性能,不仅在网络调用时会降低,在拷贝对象以便用于网络中发送时也会降低。

6 EJB实例学习
EJB远程接口
Public interface Agency extends EJBObject
{
//方法声明
}
定义接口后,有一个实现接口后面的业务逻辑的任务。EJB的业务逻辑存在于bean类中,这个bean包括两个部分:
(1) 业务逻辑本身,包含远程接口中定义的方法的实现
Bean本身不实现那些远程接口,可以通过设置EJB配置信息中的属性来请求 容器 代表EJB应用诸如访问控制之类的服务,所以当容器接收到方法调用后,判断是否需要应用其他额外的服务,通过一个bean的服务端代理,实现EJB远程接口,客户端通过调用代理实现的业务方法,然后代理应用需要的额外服务,最后将方法调用传递到bean本身



Public class AgencyBean implements SessionBean
{
//接口实现,但不继承自Agency
}

(2) 一套运行容器管理bean生命周期的方法
EJB环境的目的是允许我们将大多数时间用在编写业务逻辑而不是网络或者书籍的通道,除此以外,bean的开发人员要做的就是提供允许容器管理bean的生命周期的钩子。
Public class AgencyBean implements SessionBean
{
Public void ejbCreate() throws CreateException
{}
}

(3) 客户端使用EJB
为了方便EJB的创建和发现,每种类型的EJB都提供了一个本地接口,Bean开发人员提供一个EJB本地接口作为这个EJB的工厂
我们可以通过EJBhome接口中的create方法来创建实例,也可以使用findxx来查找现有的ejb
Public interface AgencyHome extends EJBHome
{
Agency create() throws RemoteException,CreateException;
}




7 如何创建EJB
EJB的创建机制
(1) 设计和定义业务接口,包括解决方案的UML模型到java类的映射
(2) 决定使用哪种合适的bean
(3) 根据不同的bean类型决定使用哪些本地接口,也就是为ejb定义本地接口
(4) 使用正确的生命周期方法创建一个“样板”bean
(5) 填充其中的业务方法,编写业务逻辑
(6) 填充其中的生命周期方法
(7) 打包(包括部署描述符DD



EJB规范地为XML部署描述符文档(存储EJB元数据的文档)定义了一种标准的格式,所以我们想要了解EJB如何协同工作,如何提高额外信息和元数据,就可以看看其部署描述符。




8 部署EJB
EJB打包后,可以在合适的J2EE服务器中进行部署,当我们将EJB部署到某一个EJB容器中时,必须将此EJB插入到这个容器,也就是说我们需要基于EJB远程接口生成一个EJBObject,它向容器提供访问容器安全和事务信息的接口容器查看EJB提供的元数据,决定需要哪些类型的安全和事务代码。 然后 容器会同时生成本地接口实现,这样就可以调用容器定义的方法来实现EJB实例的创建,查找和销毁。 最后 容器使用JNDI注册EJB的本地接口,允许其他的应用程序组件创建和查找这类型的EJB

9 使用EJB
(1)发现EJB
客户端需要调用ejb的本地接口,所以需要取得本地接口的远程引用,在J2EE环境中,可以通过JNDI访问这类命名服务,也就是可以使用JNDI来获取EJB本地接口的引用,这是因为EJB容器使用部署中指定的JNDI名字注册了本地接口。(部属EJB时可以设置JNDI名字,客户端就通过JNDI名字来查找到这个EJB)
Try
{
InitialContext ic = new InitialContext();
Object lookup = ic.lookup(“java:comp/env/ejb/Agency”);
AgencyHome home=
(AgencyHome)PortableRemoteObject.narrow(lookup,AgencyHome.class);
}
(2)使用
Try
{
Agency agency = home.create();
//向新创建的EJB返回一个 远程引用
System.out.println(agency.getAgencyName());
}
(3) 删除
Agency =null
当本地RMI允许检测到远程对象不再有任何本地引用时,将为这个对象触发远程垃圾箱,意味着远程引用超时了,这会导致在服务器端再次引用对象,然后变销毁bean

10 EJB拓展:
EJB3.0 百度百科
EJB是sun的服务器端组件模型,最大的用处是部署分布式应用程序当然,还有许多方式可以实现分布式应用,类似微软的.net技术。凭借java跨平台的优势,用EJB技术部署的分布式系统可以不限于特定的平台。EJB (Enterprise JavaBean)是J2EE的一部分,定义了一个用于开发基于组件的企业多重应用程序的标准。其特点包括网络服务支持和核心开发工具(SDK)。 在J2EE里,Enterprise Java Beans(EJB)称为Java 企业Bean,是Java的核心代码,分别是会话Bean(Session Bean),实体Bean(Entity Bean)和消息驱动Bean(MessageDriven Bean)。

EJB简介

1.Session Bean用于实现业务逻辑,它可以是有状态的,也可以是无状态的。每当客户端请求时,容器就会选择一个Session Bean来为客户端服务。Session Bean可以直接访问数据库,但更多时候,它会通过Entity Bean实现数据访问。
2.Entity Bean是域模型对象,用于实现O/R映射,负责将数据库中的表记录映射为内存中的Entity对象,事实上,创建一个Entity Bean对象相当于新建一条记录,删除一个Entity Bean会同时从数据库中删除对应记录,修改一个Entity Bean时,容器会自动将Entity Bean的状态和数据库同步
3.MessageDriven Bean是EJB2.0中引入的新的企业Bean,它基于JMS消息,只能接收客户端发送的JMS消息然后处理。MDB实际上是一个异步的无状态Session Bean,客户端调用MDB后无需等待,立刻返回,MDB将异步处理客户请求。这适合于需要异步处理请求的场合,比如订单处理,这样就能避免客户端长时间的等待一个方法调用直到返回结果。
EJB实际上是SUN的J2EE中的一套规范,并且规定了一系列的API用来实现把EJB概念转换成EJB产品.EJB是BEANS,BEANS是什么概念,那就是得有一个容纳她,让她可劲造腾的地方,就是得有容器.EJB必须生存在EJB容器中.这个容器可是功能强大之极!她首先要包装你BEAN,EJB的客户程序实际上从来就不和你编写的EJB直接打交道,他们之间是通过LOCAL/REMOTE接口来发生关系的.它负责你的BEAN的所有的吃喝拉撒睡,比如BEAN的持续化,安全性,事务管理...



一.什么是 EJB?
一个技术规范:EJB 从技术上而言不是一种"产品"
EJB 是一种标准描述了构建应用组件要解决的:
可扩展 (Scalable)
分布式 (Distributed)
事务处理 (Transactional)
数据存储 (Persistent)
安全性 (Secure)
二.Sun 对 EJB 的期望
提供一个标准的分布的、基于 OO 的组件架构
屏蔽复杂的系统级功能需求
Write once, run anywhere
与非 Java 应用之间的互操作能力
兼容CORBA 标准
三.为什么选择 EJB?
EJB 服务器完成"繁杂"的工作:应用开发人员关注于业务逻辑的实现而不是底层的实现机制(类似于 4GL 语言设计的目标)
支持事务处理
多个业务操作同时成功,或全部失败
可以通过在代码外的描述来定义事务处理级别

可扩展性
EJB 可以根据您应用的增长而扩展
EJB 服务器往往还提供了负载均衡和
安全性:由 EJB 服务器提供资源的访问权限控制
四.EJB 架构
为了满足架构的目标,规范中描述了
服务器 (Server)
容器 (Container)
类 (Class) 和实例 (Instance)
Home 和 Remote 接口
客户端 (Client)
五. 简化的编程模型
关注于业务逻辑实现:EJB 负责生命周期 (lifecycle), 数据存储 (persistence), 事务处理语义 (transactional semantic), 安全(security), ...
通用的编程模型:各种服务的高层 API
Java 是其编程语言
EJB( 业务逻辑代码 ) 表示了与特定商业领域(例如银行、零售等行业)相适应的逻辑。它由运行在业务逻辑层的 enterprise bean 处理。一个 enterprise bean 可以从客户端接受数据,对它进行处理,并将其发送到企业信息系统层以作存储;同时它也可以从存储器获取数据,处理后将其发送到客户端应用程序
有三种类型的 enterprise beans:session beans、entity beans 和 message-driven beans。
Session bean 描述了与客户端的一个短暂的会话。当客户端的执行完成后,session bean 和它的数据都将消失;与之相对应的是一个 entity bean 描述了存储在数据库表中的一行持久稳固的数据,如果客户端终止或者服务结束,底层的服务会负责 entity bean 数据的存储。
Message-driven bean 结合了 session bean 和 Java 信息服务(JMS)信息监听者的功能,它允许一个商业组件异步地接受 JMS 消息。

EJB3.0的介绍

由于EJB2.0的复杂性,在Spring和Hibernate等轻量级框架出现后,大量的用户转向了,在大家的呼声中,期待已久的EJB3.0规范终于发布了。在本文中将对新的规范进行一个概要性的介绍,包括新增的元数据支持,EJBQL的修改,实体Bean模型访问 bean上下文的新方法和运行时环境等等。作者还讨论了EJB在未来要作出的调整以及EJB3.0与其他开发规范之间的关系。
开始
无论如何由于EJB的复杂性使之在J2EE架构中的表现一直不是很好。EJB大概是J2EE架构中唯一一个没有兑现其能够简单开发并提高生产力的组件。EJB3.0规范正尝试在这方面作出努力以减轻其开发的复杂性。EJB3.0减轻了开发人员进行底层开发的工作量,它取消或最小化了很多(以前这些是必须实现)回调方法的实现,并且降低了实体Bean及O/R映射模型的复杂性。
在本文中,我首先会介绍EJB3.0中几个主要的改变。它对进一步深入了解EJB3.0是非常重要的。随后,我会从更高的层面来描述已经被提交到EJB3.0规范中的细节,并一个个的讲解新的规范中的改变:实体Bean,O/R映射模型,实体关系模型和EJB QL(EJB查询语言)等等。
背景
[align=left]EJB3.0中两个重要的变更分别是:使用了Java5中的程序注释工具基于Hibernate的O/R映射模型。[/align]




EJB
Java5中的元数据工具
Java5(以前叫J2SE1.5或Tiger) 中加入了一种新的程序注释工具。通过这个工具你可以自定义注释标记,通过这些自定义标记来注释字段、方法、类等等。这些注释并不会影响程序的语义,但是可以通过工具(编译时或运行时)来解释这些标记并产生附加的内容(比如部署描述文件),或者强制某些必须的运行时行为(比如EJB组件的状态特性)。注释的解析可以通过源文件的解析(比如编译器或这IDE工具)或者使用Java5中的APIs反射机制。注释只能被定义在源代码层。由于所有被提交到 EJB3.0草案中的注释标记都有一个运行时的RetentionPolicy,因此会增加类文件占用的存储空间,但这却给容器制造商和工具制造商带来了方便。
Hibernate
目前Hibernate非常受欢迎,它是开发源代码的Java O/R映射框架,目的是把开发人员从繁琐的数据持久化编程中解脱出来。它也有一个标准的HQL(Hibernate 查询语言)语言,你可以在新的EJB QL中看到它的影子。Hibernate在处理如数据查询、更新、连接池、事务处理、实体关系处理等方面非常简单。
概览
在已经提交的EJB3.0规范中主要涉及两个方面的改变:
1. 一套以注释为基础的EJB编程模型,再加上EJB2.1中定义的通过部署描述符和几个接口定义的应用程序行为。
2. 新的实体Bean持久化模型,EJBQL也有许多重要的改变。
还有一些有关上述的提议,比如:一个新的客户端编程模型,业务接口的使用以及实体Bean的生命周期。请注意EJB2.1编程模型(包括部署描述符和home/remote接口)仍然是有效的。新的简化模型并没有完全取代EJB2.1模型。

编辑本段EJB注释

EJB规范组织一个重要的目标是减轻原始代码的数量,并且他们为此给出了一个完美而简洁的办法。在
EJB3.0的里,任何类型的企业级 Bean只是一个加了适当注释的简单Java对象(POJO)。注释可以用于定义bean的业务接口、O/R映射信息、资源引用信息,效果与在 EJB2.1中定义部署描述符和接口是一样的。在EJB3.0中部署描述符不再是必须的了;home接口也没有了,你也不必实现业务接口(容器可以为你完成这些事情)。
比如,你可以使用@Stateless注释标记类把Java类声明为一个无状态会话bean。对于有状态会话bean来说,@Remove注释可以用来标记一个特定的方法,通过这个注释来说明在调用这个方法之后bean的实例将被清除掉。
为了减少描述组件的说明信息,规范组织还采纳了由异常进行配置(configuration-by-exception)的手段,意思是你可以为所有的注释提供一个明确的缺省值,这样多数常规信息就可以据此推断得出。
新的持久化模型
新的实体bean也是一个加了注释的简单Java对象(POJO)。一旦它被EntityManager访问它就成为了一个持久化对象,并且成为了持久化上下文(context)的一部分。一个持久化上下文与一个事务上下文是松耦合的;严格的讲,它隐含的与一个事务会话共存。
实体关系也是通过注释来定义的,O/R映射也是,并提供几种不同的数据库规范操作,在EJB2.1中这些
要通过开发人员自己的设计模式或者其它技术来完成的(比如,自增长主键策略)。
深入研究
现在是时候详细了解EJB3.0草案了。让我们开始探讨所有EJB中四种企业级bean,并看看他们在新的规范中是什么样子。
无状态会话bean
在EJB3.0规范中,写一个无状态会话bean(SLSB)只需要一个简单的Java文件并在类层加上@Stateless注释就可以了。这个bean可以扩展javax.ejb.SessionBean接口,但这些不是必须的。
一个SLSB不再需要home接口,没有哪类EJB再需要它了。Bean类可以实现业务接口也可以不实现它。如果没有实现任何业务接口,业务接口会由任意public的方法产生。如果只有几个业务方法会被暴露在业务接口中,这些方法可以使用@BusinessMethod注释。缺省情况下所有产 生的接口都是local(本地)接口,你也可以使用@Remote注释来声明这个接口为remote(远程)接口。
下面的几行代码就可以定义一个HelloWorldbean了。而在EJB2.1中同样的bean至少需要两个接口,一个实现类和几个空的实现方法,再加上部署描述符。
import javax.ejb.*;
/**
* A stateless session bean requesting that a remote business
* interface be generated for it.
*/
;@Stateless
;@Remote
public class HelloWorldBean {
public String sayHello() {
return "Hello World!!!";
}
}
有状态会话bean
除了几个SFSB的特别说明之外,有状态会话bean(SFSB)和SLSB一样精简:
一个SFSB应该有一个方法来初始化自己(在EJB2.1中是通过ejbCreate()来实现的)。在EJB3.0的规范中建议这些初始化操作可以通过自定义方法完成,并把他们暴露在业务接口中。在使用这个bean之前由客户端来调用相应的初始化方法。目前规范组织就是否提供一个注释来标记某个方法用于初始化还存在争议。
Bean的提供者可以用@Remove注释来标记任何SFSB的方法,以说明这个方法被调用之后bean的实例将被移除。同样,规范组织仍然在讨论是否要有一种机制来处理这种特殊的情况,即当这个方法出现异常的情况下bean的实例是否被移除。
下面是对以上问题我个人的观点:
是否应该有一个注释来标明一个方法进行初始化呢?我的观点是――应该有,这样容器就可以在调用其他方法之前至少调用一个方法来进行初始化。这不仅可以避免不必要的错误(由于没有调用初始化方法)而且可以使容器更明确的判断是否可以重用SFSB实例。我暂且把这个问题放一放,规范组织只考虑为一个方法提供一个注释来声明它是一个初始化方法。
对于第二个问题我的观点也是肯定的。这有利于Bean的提供者合客户端程序对其进行控制。只有一个遗留的问题:那就是一旦调用这个方法失败,是否能移除这个bean 的实例?答案是不能,但是它将会在会话结束的时候被移除
消息驱动Bean
消息驱动Bean是唯一一种必须实现一个业务接口的Bean。这个接口指出bean支持的是哪一种消息系统。对于以JMS为基础的MDB来说,这个接口是javax.jms.MessageListener。注意MDB业务接口不是一个真正意义上的业务接口,它只是一个消息接口。
实体Bean
实体Bean使用@Entity注释来标记,所有实体bean中的属性/字段不必使用@Transient注释来标记。实体bean的持久化字段可以通过JavaBean-style机制或者声明为public/protected字段来实现。
实体bean可以使用助手类来描述其状态,但是这些类的实例并没有持久化唯一性(persistent identity)的特性(即,唯一标识这个bean的字段等),实际上这些助手类与他们的实体bean实例是紧密结合的;并且这些对象还是以非共享方式来访问实体对象的。
实体关联
EJB3.0同时支持Bean之间双向的合单向的关联,它们可以是一对一、一对多、多对一或者是多对多的关联。然而双向关联的两端还要分为自身端 (owning side)和对方端(inverse side)不同的端。自身端负责向数据库通告关联的变更。对于多对多的关联自身端必须明确的声明。实际上对方端通过isInverse=true进行注释 (由此自身端就不必说明了而是由另一段推断出)。看来上面的描述,规范组织还能说让EJB变的简单了吗?
O/R映射
EJB3.0中的O/R映射模型也有了重要的改变,它从原来的abstract-persistence-schema-based变成了现在的Hibernate-inspired模式。尽管目前规范组织还在就此进行讨论但是一个明确的模型将会出现在下一个版本的草案中。
举例来说,O/R映射模型将通过bean类中的注释来声明。而且此方法还会指出对应的具体表和字段。O/R映射模型提供了一套自有的SQL; 而且除了提供一些基本的SQL外还支持某些高层开发的功能。比如,有一个通过@Column注释声明的字段columnDefinition,那么可以写这 样的SQL:columnDefinition="BLOB NOT NULL"
客户端程序模型
一个EJB客户端可以通过@Inject注释以一种“注入”的方式获得一个bean的业务接口引用。你也可以使用另一个注释 @javax.ejb.EJBContext.lookup()来完成上面的操作,但是规范中没有告诉我们一个普通的Java客户端怎样获得一个Bean 的实例,因为这个普通的Java客户端是运行在一个客户端容器中,它无法访问@javax.ejb.EJBContex对象。现在还有另外一种机制来完成上面的工作那就是使用一个超级上下文环境对象:@javax.ejb.Context()。但是规范中没有指出该如何在客户端中使用这个对象。
EJB QL
EJB QL可以通过@NamedQuery来注释。这个注释有两个成员属性分别是name和queryString.一旦定义了这些属性,就可以通过 EntityManager.createNamedQuery(name)来指向这个查询。你也可以创建一个标准的JDBC风格的查询并使用 EntityManager.createQuery(ejbqlString)或EntityManager.createNativeQuery (nativeSqlString)(这个方法用于执行一个本地查询)来执行查询。
EJB QL有两个地方可以定义其参数。javax.ejb.Query接口提供了定义参数、指向查询、更新数据等等方法。下面是一个EJBQL指向查询的例子:
查看复制到剪切板打印
. ..
;@NamedQuery(
name="findAllCustomersWithName",
queryString="SELECT c FROM Customer c WHERE c name LIKE :custName"
)
.. ..
;@Inject public EntityManager em;
customers = em.createNamedQuery("findAllCustomersWithName")
.setParameter("custName", "Smith")
.listResults();
下面列出了一些EJB QL的增强特性:
支持批量更新和删除
直接支持内连接和外连接。FETCH JOIN运行你指出关联的实体,Order可以指定只查询某个字段。
查询语句可以返回一个以上的结果值。实际上,你可以返回一个依赖的类比如下面这样:
SELECT new CustomerDetails(c id, c.status, o.count)
FROM Customer c JOIN c.orders o
WHERE o.count > 100 l 支持group by 和having。
支持where子句的嵌套子查询
在提交的EJB3.0草案中,EJB QL与标准SQL非常的接近。实际上规范中甚至直接支持本地的SQL(就像我们上面提到的那样)。这一点对某些程序员来说也许有些不是很清楚,我们将在下面进行更详细的讲解。
多样性
方法许可(Method permissions)可以通过@MethodPermissions和@Unchecked注释来声明;同样的,事务属性也可以通过 @TransactionAttribute注释来声明。规范中仍然保留资源引用和资源环境引用。这些一样可以通过注释来声明,但是有一些细微的差别。比如,上下文(context)环境要通过注入工具控制。容器根据bean对外部环境引用自动初始化一个适当的已经声明的实例变量。比如,你可以象下面这样获得一个数据源(DataSource):
;@Resource(name="myDataSource") //Type is inferred from variable
public DataSource customerDB;
在上面的例子中如果你不指定引用资源的名称(name)那么其中的customerDB会被认为是默认值。当所有的引用属性都可得到时候@Injec注释就可以这样写:
查看复制到剪切板打印
1. ;@Inject public DataSource customerDB;
;@Inject public DataSource customerDB;
容器负责在运行时初始化customerDB数据源实例。部署人员必须在此之前在容器中定义好这些资源属性。
更好的消息是:那些以前必须检测的异常将一去不复返。你可以声明任意的应用程序异常,而不必在再抛出或捕获其他类似 CreateException和FinderException这样的异常。容器会抛出封装在javax.ejb.EJBException中的系统级异常或者只在必要时候抛出IllegalArgumentException或IllegalStateException异常。

编辑本段EJB文件处理模式

在我们结束本节之前,让我的快速的浏览一下容器提供商在EJB处理模式方面可能的变更。规范中对此并没有明确的表态,但我可以想到至少两种模式。
一种办法是首先利用EJB文件生成类似于EJB2.1部署模式的文件(包括必要的接口和部署描述符)然后再用类似于EJB2.1的方式来部署这个EJB组件。当然,这样产生的部署描述符可能并不标准但是它可以解决同一个容器对EJB2.1和EJB3.0兼容的问题。下面这幅图描述了这一过程。
另一种方法是一种类似于JSP托放的部署模式。你可以把一个EJB文件放到一个预先定义的目录下,然后容器会识别这个EJB并处理它,然后部署并使之可以使用。这种方法可以建立于上面那种方法之上,在支持反复部署时有很大的帮助。考虑到部署的简单性也是EJB3.0规范的目的之一,我真诚的希望在下一个草案出来时能够确定一个模式(至少能有一个非正式的)。
你有什么想法?
EJB3.0规范的制定正在有序的进行,为了使EJB的开发变得更加容易,EJB规范组织作出的努力是有目共睹的。就像他们说的那样,一切对会变得简单,但做到这一点并不容易。目前已经定义了50个注释标记(还有几个将在下一个草案中发布),每一个都有自己的缺省规则和其他的操作。当然,我真的不希望EJB3.0变成EJB2.1的一个翻版"EJB 3.0 = EJB 2.1 for dummies"(希望这个等式不要成立)。最后,我还是忍不住要提一些我自己的观点:
首先,规范确实使反复部署变得容易了,并且有一个简单的模式来访问运行时环境。我还是觉得home接口应该放弃。
在早期的EJB规范中,实体bean用于映射一个持久化存储。理论上(也许只是理论上)可能需要把实体bean映射到一个遗留的EIS (enterprise information system)系统中。出于将来扩展的考虑这样作是有好处的,并且可以使更多的业务数据模型采用实体bean。也因此其伴随的复杂性使得实体bean不被看好。在本次提交的草案中,一个实体bean只是一个数据库的映射。并且是基于非抽象持久化模式和简单的数据访问模式的更加简单开发。
我对模型变更持保留态度,我认为在EJB中包含SQL脚本片断并不是个好注意。一些开发人员完全反对包含某些“SQL片段 (SQLness)”(比如@Table 和 @Column注释)。我的观点是这些SQLness是好的,据此我们可以清楚的知道我们到底要数据库作些什么。但是某些SQL段我看来并不是很好,比如 columnDefinition="BLOB NOT NULL",这使得EJB代码和SQL之间的耦合太过紧密了。
尽管对于本地SQL的支持看似很诱人,其实在EJB代码中嵌入SQL是一个非常糟糕的主意。当然,有些办法可以避免在EJB中硬编码SQL,但是这应该在规范中说明,而不能是某些开发人员自己定义的模式。
假设@Table注释只用于类。在运行时通过@Table注释的name属性定义的表名称将必须对应一个实际的数据库表。规范对此应该给予清楚的说明和一致的模式。
规范还需要更清楚的说明客户端编程模型,尤其是普通java客户端。规范中所有的参考都假设或者隐含的使用EJB客户端。而且规范中对客户端的向后兼容方面也没有给出明确的说法。
Transient注释应该重新命名以避免和已有的transient关键字发生冲突。事实上,在这一点上我们更乐于稍微的背离一下 configuration-by-exception原则并且定义一个@Persistent注释来明确的定义持久化字段 @Persistent注释 可以仅仅是一个标记注释或者它可以有几个属性来关联O/R映射注释。

编辑本段与其他规范的关联

目前可能影响到EJB3.0的JSR有JSR175(java语言元数据工具)和JSR181(Java Web服务元数据)
JSR175已经初步完成并且不会和EJB3.0有太大的冲突;但是JSR181与EJB3.0有两个关联的地方:
Web service接口:EJB规范将采用一种机制适应JSR181以便可以把一个bean实现为一个Web service并告诉Web service如何被客户端调用。
JSR 181计划采用不同的机制来处理安全问题。在早期的规范中EJB建议使用一个一致的机制(MethodPermissions),但是JSR 181计划使用一个稍微不同的方式(SecurityRoles和SecurityIdentity注释)。同样的RunAs注释的定义也存在这些许差别。这一问题还在解决中最终会在J2EE层的规范中维持其一致性。
在J2EE 1.5中的一些开发规范可能与EJB3.0有关联。除了上面说到的几个关联之外现在没有其他的开发规范与EJB3.0有冲突。

编辑本段关于EJB3.1

对于EJB,优先考虑的就是全部重建。“我们只有先清空杯子里的水,才能接纳新的东西”。现在杯子已经清空了,这对我们来说是非常有利的,而且还可以没有包袱的大胆前进。
EJB3.1 又一次引入了一系列新的特性,倾向于挖掘技术的潜力。依我来看,EJB3.1绝对是一个重要的发布版本,它将那些长期让人渴望的特性带到开发者面前,更加能够满足最新的企业应用程序开发,同时对EJB再次被人们采纳将做出巨大的贡献。
目前,EJB 3.1 最终发行版已经发布了。
EJB3.1架构模式相对于旧的架构模式有如下的一些扩展和针对API的一些简化:
· 简化的本地模式让去除了本地的商务接口一样可达到session bean
· 直接用war文件打包一个ejb组件不需要一个ejb-jar
· 在Java SE环境中嵌入API执行EJB
· 引入了可以提供简单的共享应用数据和支持一致性访问的Singleton session bean组件
· 自动创建EJB定时器
· 基于EJB定时表达式的日程表
· 异步session bean调用
· 对于一个EJB轻量子集的定义,这个子集可以提供一些Java EE文档 (EJB lite)
· 一个用来查询ejb组件的Global JNDInames( 统一的 全局 JNDI 命名 ) 规则

编辑本段结束语

在使EJB的开发变得简单高效之前,我们还有很长一段路要走。规范组织在降低EJB的开发难度方面起了个好头。O/R映射模型的提议还处在早期阶段,规范组织正在完善它。我希望它不要太复杂也不要与SQL过分的耦合。
其他
通过jsp页面使用EJB返回结果
(1) 浏览器请求abc.jsp文件
(2) 应用服务器的jsp引擎 编译abc.jsp
(3) abc.jsp中的代码通过JNDI查找 EJB,获得EJB的stub(代理存根),调用存根的function,这时候EJB所在的容器截获方法调用
(4) EJB容器调用EJB实例的function方法。


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: