本书从EJB 3最基本的内容讲起,接着逐步讲解了EJB 3应用程序开发的整个过程,涉及EJB 3规范的各个方面,并将许多实践经验融入整个EJB架构,提供了对EJB 3架构和EJB 3编程全面的实战性指导,充分体现了EJB 3强大的功能和易于使用的特点。 \r\n 本书主要面向Java和J2EE开发人员。
第1章 EJB 3架构简介 \r\n 1.1 EJB简介 \r\n 1.1.1 EJB是什么\r\n 1.1.2 EJB组件模型 \r\n 1.1.3 EJB框架 \r\n 1.1.4 EJB核心特性 \r\n 1.1.5 EJB规范的发展 \r\n 1.1.6 EJB 3简化开发模型 \r\n 1.1.7 分布式计算模型 \r\n 1.1.8 EJB角色\r\n 1.2 本书结构 \r\n 1.3 准备 \r\n 1.3.1 安装GlassFish应用程序服务器的先决条件 \r\n 1.3.2 安装GlassFish应用程序服务器 \r\n 1.3.3 环境变量设置 \r\n 1.3.4 密码文件的创建 \r\n 1.3.5 启动和测试GlassFish安装 \r\n 1.4 小结 \r\n第2章 EJB 3会话bean \r\n 2.1 简介 \r\n 2.2 会话bean简介 \r\n 2.2.1 会话bean类型 \r\n 2.2.2 何时使用会话bean \r\n 2.3 无状态会话bean \r\n 2.3.1 bean类 \r\n 2.3.2 业务接口 \r\n 2.3.3 业务方法 \r\n 2.3.4 依赖注入 \r\n 2.3.5 回调方法 \r\n 2.3.6 拦截器 \r\n 2.4 有状态会话bean \r\n 2.4.1 bean类 \r\n 2.4.2 业务接口 \r\n 2.4.3 业务方法 \r\n 2.4.4 回调方法 \r\n 2.4.5 拦截器 \r\n 2.4.6 异常处理 \r\n 2.5 会话bean的客户视图 \r\n 2.6 会话bean的打包、部署和测试 \r\n 2.6.1 先决条件 \r\n 2.6.2 编译会话bean \r\n 2.6.3 打包会话bean \r\n 2.6.4 部署会话bean \r\n 2.6.5 编译客户程序 \r\n 2.6.6 运行客户程序 \r\n 2.7 小结 \r\n第3章 实体和JPA \r\n 3.1 实体示例 \r\n 3.1.1 简单JavaBean Customer.java \r\n 3.1.2 简单实体Customer.java \r\n 3.1.3 显示了默认设置的实体Customer.java \r\n 3.1.4 代码要求 \r\n 3.1.5 示例:注解实例变量 \r\n 3.1.6 示例:注解属性访问方法 \r\n 3.1.7 声明主键 \r\n 3.1.8 简单主键 \r\n 3.1.9 复合主键 \r\n 3.1.10 实体示例小结 \r\n 3.2 持久化档案 \r\n 3.3 EntityManager \r\n 3.3.1 持久化上下文 \r\n 3.3.2 获得EntityManager实例 \r\n 3.3.3 事务支持 \r\n 3.4 实体生存周期 \r\n 3.5 O/R映射 \r\n 3.5.1 再谈@Table注解 \r\n 3.5.2 再谈@Column注解 \r\n 3.5.3 复杂映射 \r\n 3.6 实体关系 \r\n 3.6.1 @OneToOne \r\n 3.6.2 @OneToMany和@ManyToOne \r\n 3.6.3 @ManyToMany \r\n 3.6.4 延迟和预先字段绑定 \r\n 3.6.5 层叠操作 \r\n 3.7 JPQL\r\n 3.7.1 @NamedQuery和@NamedQueries \r\n 3.7.2 绑定查询参数 \r\n 3.7.3 动态查询 \r\n 3.7.4 批更新和删除操作 \r\n 3.7.5 复杂查询 \r\n 3.8 向前生成与反向工程 \r\n 3.8.1 向前生成产生持久性 \r\n 3.8.2 反向工程产生适应性 \r\n 3.8.3 哪种方式适用于你的工程 \r\n 3.9 示例应用程序CustomerOrderManager \r\n 3.9.1 Customer.java \r\n 3.9.2 CustomerOrder.java \r\n 3.9.3 Address.java \r\n 3.9.4 CustomerOrderManager.java \r\n 3.9.5 CustomerOrderClient.java \r\n 3.9.6 persistence.xml \r\n 3.10 小结 \r\n第4章 高级持久化特性 \r\n 4.1 映射实体继承层次结构 \r\n 4.1.1 准备 \r\n 4.1.2 实体继承映射策略 \r\n 4.1.3 每个类单一表的继承层次结构(InheritanceType.SINGLE_TABLE) \r\n 4.1.4 带有连接子类表的通用基表(InheritanceType.JOINED) \r\n 4.1.5 每个最外层一个表的具体实体类(InheritanceType.TABLE_PER_CLASS) \r\n 4.1.6 O/R实现方式的比较 \r\n 4.2 在继承层次结构中使用抽象实体、映射的超类和非实体类 \r\n 4.2.1 抽象实体类 \r\n 4.2.2 映射的超类(@MappedSuper-class) \r\n 4.2.3 非实体类 \r\n 4.2.4 使用嵌入非实体类(@Embeddable和@Embedded) \r\n 4.3 多态关系 \r\n 4.4 多态JPQL查询 \r\n 4.5 使用原生SQL查询 \r\n 4.6 复合主键和嵌套外键 \r\n 4.6.1 使用嵌套复合键(@EmbeddedId) \r\n 4.6.2 在实体类上直接暴露复合键类字段(@IdClass) \r\n 4.6.3 使用复合键的映射关系 \r\n 4.7 乐观锁定的支持(@Version) \r\n 4.8 自动生成的主键值的支持 \r\n 4.9 拦截器:实体回调方法 \r\n 4.10 小结 \r\n第5章 EJB 3消息驱动bean \r\n 5.1 简介 \r\n 5.2 面向消息的架构 \r\n 5.2.1 JMS是什么 \r\n 5.2.2 消息应用程序架构 \r\n 5.3 使用MDB \r\n 5.3.1 何时使用MDB \r\n 5.3.2 MDB类 \r\n 5.3.3 配置属性 \r\n 5.3.4 MDB中的依赖注入 \r\n 5.3.5 回调方法 \r\n 5.3.6 拦截器 \r\n 5.3.7 异常处理 \r\n 5.3.8 客户视图 \r\n 5.4 MDB的打包、部署和测试 \r\n 5.4.1 先决条件 \r\n 5.4.2 编译会话bean和MDB \r\n 5.4.3 打包会话bean和MDB \r\n 5.4.4 创建JMS和JavaMail资源 \r\n 5.4.5 部署会话bean和MDB \r\n 5.4.6 编译客户程序 \r\n 5.4.7 运行客户程序 \r\n 5.5 小结 \r\n第6章 EJB 3和Web服务 \r\n 6.1 简介 \r\n 6.2 Web服务是什么 \r\n 6.2.1 UDDI \r\n 6.2.2 WSDL \r\n 6.2.3 SOAP \r\n 6.2.4 何时使用Web服务 \r\n 6.3 Java EE和Web服务 \r\n 6.3.1 JAX-WS \r\n 6.3.2 JAXB \r\n 6.3.3 JAXR \r\n 6.3.4 SAAJ \r\n 6.3.5 JSR 181 \r\n 6.4 EJB 3无状态会话bean作为Web服务 \r\n 6.5 Web服务的打包、部署和测试 \r\n 6.5.1 先决条件 \r\n 6.5.2 编译会话bean \r\n 6.5.3 打包会话bean \r\n 6.5.4 部署会话bean \r\n 6.5.5 使用GlassFish控制台测试信用卡服务 \r\n 6.6 Web服务客户视图 \r\n 6.6.1 开发访问Web服务的Java客户程序 \r\n 6.6.2 会话bean作为Web服务客户程序 \r\n 6.7 小结 \r\n第7章 集成会话bean、实体、消息驱动bean和Web服务 \r\n 7.1 简介 \r\n 7.2 应用程序概述 \r\n 7.3 应用程序组件和服务 \r\n 7.3.1 购物车组件 \r\n 7.3.2 搜索外观组件 \r\n 7.3.3 顾客外观组件 \r\n 7.3.4 订单处理外观组件 \r\n 7.3.5 持久化服务 \r\n 7.3.6 电子邮件服务 \r\n 7.3.7 信用卡服务 \r\n 7.3.8 订单处理服务 \r\n 7.4 酒类在线应用程序业务处理 \r\n 7.5 深入讲解组件/服务 \r\n 7.5.1 持久化服务 \r\n 7.5.2 顾客外观组件 \r\n 7.5.3 搜索外观组件\r\n 7.5.4 购物车组件 \r\n 7.5.5 订单处理外观组件 \r\n 7.5.6 订单处理服务 \r\n 7.5.7 电子邮件服务 \r\n 7.5.8 信用卡服务 \r\n 7.5.9 数据库schema \r\n 7.6 打包、部署和测试应用程序 \r\n 7.6.1 先决条件 \r\n 7.6.2 部署信用卡服务 \r\n 7.6.3 编译持久化单元 \r\n 7.6.4 打包持久化单元 \r\n 7.6.5 编译业务服务(会话bean和MDB) \r\n 7.6.6 打包业务服务 \r\n 7.6.7 汇编应用程序 \r\n 7.6.8 创建数据库schema \r\n 7.6.9 创建数据源、JMS资源和Mail资源 \r\n 7.6.10 部署应用程序 \r\n 7.7 应用程序的简单测试客户程序 \r\n 7.8 小结 \r\n第8章 EJB 3中的事务支持 \r\n 8.1 事务是什么 \r\n 8.1.1 分布式事务 \r\n 8.1.2 事务的ACID属性 \r\n 8.1.3 JTA \r\n 8.1.4 两阶段提交协议 \r\n 8.2 EJB中的事务支持 \r\n 8.3 服务模型中的会话bean事务行为 \r\n 8.3.1 容器管理的事务分界 \r\n 8.3.2 bean管理的事务分界 \r\n 8.4 持久化模型中的实体事务行为 \r\n 8.4.1 实体如何与事务上下文相关联 \r\n 8.4.2 容器管理与应用程序管理的持久化上下文 \r\n 8.4.3 事务范围的持久化上下文与扩展的持久化上下文 \r\n 8.4.4 JTA与资源本地的Entity-Manager \r\n 8.5 酒类在线应用程序的事务场景 \r\n 8.5.1 设置示例 \r\n 8.5.2 使用CMT分界的无状态会话bean \r\n 8.5.3 使用BMT分界的有状态会话bean和扩展的持久化上下文 \r\n 8.6 小结 \r\n第9章 EJB 3性能和测试 \r\n 9.1 测试方法论 \r\n 9.1.1 性能标准 \r\n 9.1.2 模拟应用程序使用 \r\n 9.1.3 定义测试尺度 \r\n 9.2 Grinder \r\n 9.3 测试应用程序 \r\n 9.4 性能测试 \r\n 9.4.1 测试环境 \r\n 9.4.2 测试脚本\r\n 9.4.3 设置 \r\n 9.4.4 初步测试 \r\n 9.4.5 样本大小 \r\n 9.4.6 校准 \r\n 9.4.7 实际测试运行 \r\n 9.4.8 分析结果 \r\n 9.5 小结 \r\n第10 章 把EJB 2.x应用程序迁移到EJB 3 \r\n 10.1 准备 \r\n 10.2 会话bean迁移 \r\n 10.2.1 EJB 2.1会话bean \r\n 10.2.2 EJB 2.1的ejb-jar.xml文件\r\n 10.2.3 EJB 3会话bean类 \r\n 10.2.4 迁移EJB 2.1会话bean类 \r\n 10.2.5 迁移EJB 2.1会话bean接口 \r\n 10.2.6 迁移EJB 2.1会话bean的ejb-jar.xml属性 \r\n 10.2.7 迁移EJB 2.1的Web服务端点接口 \r\n 10.2.8 会话bean迁移包装 \r\n 10.3 MDB迁移 \r\n 10.4 实体bean迁移 \r\n 10.5 EJB客户程序迁移 \r\n 10.6 完整的应用程序迁移示例 \r\n 10.6.1 EJB 2.1应用程序源文件 \r\n 10.6.2 EJB 3应用程序源文件 \r\n 10.7 把我们的应用程序迁移在Java EE容器之外运行 \r\n 10.7.1 EJB 3会话bean类运行在EJB容器之外 \r\n 10.7.2 容器外部持久化单元的EJB 3的persistence.xml文件 \r\n 10.7.3 EJB 3应用程序管理的EntityManager客户程序 \r\n 10.8 小结 \r\n第11章 EJB 3部署 \r\n 11.1 部署工具简介 \r\n 11.2 部署过程概述 \r\n 11.2.1 提供者 \r\n 11.2.2 装配者 \r\n 11.2.3 部署者 \r\n 11.3 Java EE部署基础结构 \r\n 11.3.1 Java EE服务器 \r\n 11.3.2 Java EE容器 \r\n 11.4 Java EE部署组件 \r\n 11.4.1 Java EE应用程序 \r\n 11.4.2 Java EE模块类型 \r\n 11.4.3 库组件 \r\n 11.5 应用服务器和平台无关性 \r\n 11.5.1 部署工具 \r\n 11.5.2 部署计划\r\n 11.6 部署角色 \r\n 11.6.1 应用程序装配者 \r\n 11.6.2 应用程序部署者 \r\n 11.7 汇编EJB JAR模块 \r\n 11.8 汇编持久化单元 \r\n 11.9 小结 \r\n第12章 EJB 3客户应用程序 \r\n 12.1 应用程序架构 \r\n 12.2 JSF \r\n 12.2.1 Java EE Web技术的发展 \r\n 12.2.2 JSF架构 \r\n 12.2.3 JSF工具和组件 \r\n 12.3 使用JSF和EJB开发Web应用程序 \r\n 12.3.1 登录页面 \r\n 12.3.2 新用户注册页面 \r\n 12.3.3 链接页面 \r\n 12.3.4 搜索页面\r\n 12.3.5 酒类清单页面 \r\n 12.3.6 显示选定的酒类详细信息页面 \r\n 12.3.7 显示购物车项目页面 \r\n 12.3.8 通知页面 \r\n 12.4 打包、部署和测试应用程序 \r\n 12.4.1 先决条件 \r\n 12.4.2 编译和打包JSF应用程序 \r\n 12.4.3 汇编酒类商店应用程序 \r\n 12.4.4 部署酒类商店应用程序 \r\n 12.4.5 运行酒类商店应用程序 \r\n 12.5 应用程序客户容器 \r\n 12.6 小结 \r\n附录
EJB 3是EJB规范的一个非常重要的里程碑,不仅因为它更加容易使用,而且因为它是第一次(在我看来)根据开发社区的需求创建的,是已有的最佳实践经验的标准化,而不是委员会的设计 结果。本书的主要读者应该是开发人员,所以我将从开发者的角度介绍一些EJB形成以及现在为什么如此重要的历史背景。
我经常在各种会议上演讲,在演讲时我会问有多少人使用过EJB。通常有90%的听众举手。然后,我问他们:“有多少人把EJB作为分布式对象使用——也就是说,有独立的物理层放置业务逻辑,还有独立的物理层放置表示(Servlet/JSP)层?”通常那90%的听众中只有15%举手。无论是在北美、欧洲还是日本的会议中,情形都是如此。这个结果至今让我吃惊,因为早期的EJB迫使你在代码中应用分布式语义,这对大型的多层项目是有用的,但实际上,EJB 的大多数使用者都把它作为中小型Web应用程序的本地框架。
为什么会这样呢?如果了解这段时间(1999—2003年)更为广泛的历史背景,你就会明白其中的原因了。分析一下EJB 1+所提供的核心价值,可以简单地把它们归结为以下3类。
□框架优势。当时,如果使用Java进行过Web或者企业开发工作,你会发现自己处于一个专有技术的混乱世界中;要么就只能是使用RMI和Servlet 这样的基本工具并创建自己的框架。加之当时大多数软件开发者都是随着网络公司的迅猛发展而入行的新手,因此软件行业普遍期待标准的、有共识的企业开发途径。EJB提供了这一途径——一个能够处理事务、安全、有状态组件、对象持久性等的标准框架。这一标准框架解决了实际的和当前的需求——因为当时没有开源运动,也没有出现各种Web框架。
□分布式优势。EJB标准化了使用分布式对象构建业务逻辑的编程模型和平台。这满足了随RMI和CORBA之后紧接着产生的市场需求。如果希望使用分布式对象,EJB是首选。
□组件优势。这一点有些古怪。在我看来,Sun公司在此方面的努力对Visual Basic(VB)组件市场成功的一种反应,希望在Java业务组件领域也出现同样的局面。我记得早期围绕EJB的宣传和营销主要集中在组件重用上。甚至有人曾试图为EJB组件构建在线商场。其结果是,为了EJB组件的二进制程序能跨应用程序服务器一致运行,EJB在API、部署和打包语义方面变得非常臃肿。
需要特别提到的是,Java社区对持久性标准/解决方案非常感兴趣,因为当时对象持久性的解决方案非常少,而且自己开发O/R映射程序并不是一件简单的事情。
这就是当时的背景。现在我们讲述EJB 2.1这个阶段,为此先简要回顾一下2003年年末和2004年年初的情形。在会议上谈这一话题时,我接着会从下面3个方面来介绍社区的方向(这是在EJB 3计划公之于众之前)。
□框架。这时我们有了一些可提供事务功能、池、安全和所有其他良好程序设计模型的有益于EJB的开源框架,且这些开源框架是通过更加简单和更好的方式来提供这些功能的。诸如XDoclet和Spring这样的工具,以及AOP这样的方法,都将EJB所有的框架优势引入了轻量型环境。最值得注意的是,由于普遍认为实体bean是不良的O/R映射解决方案(实际上,它们是围绕持久性组件,而不是围绕对象设计的),因而Hibernate成为了Java中最流行的O/R映射解决方案,这使得实体bean变得无足轻重了。
□分布式。RMI不再是Java远程调用事实上的标准;此时已有了其他开源API/协议。另外,SOA(面向服务的架构)原则也不赞成在分布式中使用远程对象。EJB 2.0中本地接口的引入显得很蹩脚,在很多方面使规范毫无必要地进一步复杂化了。
□组件。谁还关心它呢?企业级组件的市场消亡了。当Sun关注VB市场的成功时,他们没有注意到市场大部分是由可以在项目内重用的UI小部件和“实用工具”式的组件构成的。我们没有看到工资单类或者看到VB组件形式的“用户”。实际情况是,业务逻辑一般不能在项目之间重用,因此EJB添加的与组件相关的内容都是没有必要的。EJB JAR之间的二进制兼容性也是实际上用不到的一个特性。对于不同的应用程序服务器,通常的做法是简单地把EJB源代码添加到构建中,并且在构建时打包。如果开发可重用组件不是EJB规 范制定小组的目的,那么我们在2001年就可能已经有了接近EJB 3的东西。
现在回来思考我经常在演讲中提出的那个调查问题,请注意大部分人没有利用EJB的组件或者分布式特性。他们利用的只是EJB的框架特性,而轻量型开源框架能够更好地提供这些框架特性。在2003年,我认为EJB带来的唯一真正的价值是,用作真正大型系统的分布式对象框架——这是EJB的最初目的。因此,我对听众说:“你们误用了EJB。”我的意思是说,实际使用EJB跨物理层分布式处理业务逻辑的那15%的人没有误用EJB,他们把EJB用于必须使用分布式的情况中,而EJB确实是应对这类情况的正确技术。
那么现在的情况如何呢?依据通过Spring和Hibernate这样的框架在团队中产生的最佳实践,EJB 3最终被重新构造,为另外85%的听众进行了优化。现在我们有了一个功能强大、易于使用并且基于POJO的框架规范,该规范提供事务、安全、O/R映射和分布式,而不是一个用于构造分布式、事务和持久性组件的规范。基本拦截、依赖注入和注解驱动配置的添加也将这几年开发社区中流行的已经检验的最佳实践引入了EJB 3。
还有一件让人高兴的事,那就是我的EJB Design Patterns(中文名为《EJB设计模式》)一书(2002年出版)不会再推出新版本了。对于其中的许多模式,都已有解决方案让那85%的听众,不,是那些所有的听众能更充分地使用EJB。
EJB 3终于满足了开发者的需求,因此阅读本书是一种愉快的享受。
Floyd Marinescu
EJB Design Patterns(《EJB设计模式》)的作者
InfoQ.com社区创始人和主编
TheServerSide.com(J2EE社区)创建者
无封面