1、J2EE 体系结构1J2EE 体系结构在讨论了J2EE设计中的一些高层次问题之后,现在该来看一看J2EE应用的几个可选体系结构。常见概念首先,让我们来看一看所有J2EE体系结构都共有的几个概念。J2EE应用中的体系结构层下面要讨论的每个体系结构都含有三个主要层,尽管有些体系结构在中间层内因如了另外的划分。经验已经证明了将企业级系统明确地划分成多个层的价值。这确保了责任的明确划分。J2EE的3层体系结构是各类系统中的经验结晶。具有3个或3个以上层的系统已经证明比其内没有中间层的客户-服务器系统具有更大的可缩放和灵活性。在一个设计完备的多层系统中,每一层应该只依赖于它下面的那一层。例如,对数据库的
2、更改不应该要求对WEB接口的更改。 每一层所特有的东西应该向其他层隐藏起来。例如,WEB 应用中的 WEB 层只应该依赖于服务器小程序 API,而中间层只应该依赖于 JDBC 之类的企业资源API。这两个原则确保了应用修改起来容易,同时修改又不级联到其他层。下面依次来看典型的 J2EE 体系结构的每一层。企业信息系统(EIS)层这一层有时也叫做综合层(INTEGRATION TIER),由 J2EE 应用完成其工作所必须访问的企业资源所组成。这些资源包括数据库管理系统(DBMS)和遗留的主机应用。EIS 层资源通常是事务性的,EIS 位于 J2EE 服务器的控制之外,尽管该服务器的确以一种标准
3、方式管理事务和连接建池。J2EE 设计师对 EIS 层的设计与部署将是变化的,视该项目的性质(现有服务的绿色场或集成度)而定。如果该项目包含现有服务的集成,EIS 层资源可能会影响中间层的实现。J2EE 为与 EIS 层资源的借口提供了强有力的能力,比如访问关系数据库的JDBC API、访问目录服务器的 JNDI 以及允许连接其他 EIS 系统的 JACA CONNECTOR ARCHITECTURE (JACA 连接器体系结构,简称 JCA)。J2EE 服务器负责建立连往 EIS 资源的连接池、横跨资源上的事务管理以及保证 J2EE 应用不危及 EIS 系统的安全。J2EE 体系结构2中间层
4、这一层含有应用的业务对象,并调停对 EIS 层资源的访问。中间层构件主要从事务管理和连接建池之类的 J2EE 容器服务中受益。中间层构件独立于选定的用户接口。如果使用了 EJB,我们把中间层分离成两层:EJB 以及使用这些 EJB 来支持该接口的对象。但是,这种分离不是保证一个干净中间层所必须的。用户接口(UI)层这一层将中间业务对象暴露给用户。在 WEB 应用中,UI 层由服务器小程序所使用的助手类以及诸如 JSP 页之类的试图构件所组成。为了清楚起见,我们在讨论 WEB 应用时将把 UI 层称做“WEB 层”。业务接口的重要性许多人将 EJB 看做 J2EE 应用的核心。从 J2EE 的
5、EJB 中心论角度看,会话EJB 将暴露应用的业务逻辑,而其他对象(比如 Business Delegate J2EE 设计模式中的 Web 层“业务委托”对象)将由他们与 EJB 的关系来确定。但是,这种假设将一种技术(EJB)抬高到了 OO 设计考虑之上。EJB 不是在 J2EE 应用中实现中间层的唯一技术。正式业务接口层的概念体现了一不好的习惯,不管是不是使用了 EJB,我们都应该使用这个概念。在下面将要讨论的所有体系结构中,业务接后层都有客户(比如 UI 层)直接使用的中间层接口所组成。业务接口层为普通 Java 接口中的中间层定义了联系人;因此,EJB 就是一个实现策略。如果我们没有
6、使用 EJB,业务接口的实现将是运行在 J2EE Web 容器中的普通 Java 对象。当使用了 EJB 时,业务接口的实现将隐藏掉与 EJB 层的交互。一定要设计到 Java 接口,而不要设计到具体类,也不要设计到技术。下面来看一下满足不同需求的 4 种 J2EE 体系结构。非分布式体系结构下面的这些体系结构适合 Web 应用。他们可以把所有应用构件只运行在单个 JVM 中。这使他们变得简单而有效,但限制了部署的灵活性。具有业务构件接口的 Web 应用在大多数情况下,J2EE 用来构造 Web 应用。因此,同一个 J2EE Web 容器可以提供许多应用所需要的整个基础结构。和 EJB 一样,
7、J2EE Web 应用实际上享有对企业 API 的相同访问权。它们受益于 J2EE 服务器的事务管理和连接池能力,并可以使用 JMS,JDBC 和 Java Connector API 之类的企业服务。除实体组件之外的所有数据存取技术都是可以使用的。J2EE 体系结构3Web 应用的 Web 层和中间层运行在同一个 JVM 中。但是,在逻辑上使他们保持不同是极其重要的。Web 应用中的主要设计风险是 UI 构件与业务逻辑构件之间的责任模糊不清。业务接口层将由普通 Java 类所实现的 Java 接口来组成。这是一个简单而又可缩放的体系结构,并且能满足大多数应用的需要。长处这种体系结构具有下列优
8、点: 简单性。这通常是 Web 应用的最简单结构。但是,如果事务管理或线程化问题要求开发分复杂的代码,使用 EJB 可能将更简单。 速度。这样的体系结构遇到了来自 J2EE 服务器的最小系统开销。 OO 设计不会被 J2EE 构件问题(比如调用 EJB 的影响)所妨碍。 容易测试。如果设计合理,无需 Web 层就能够对业务接口进行测试。 我们可以发挥服务器的事务支持。 缩放性很好。如果 Web 接口是无状态的,则根本不需要来自容器的聚类支持。但是,Web 应用可以通过使用服务器支持会话状态复制来分布。弱点应该注意下列这些缺点: 这种体系结构只支持一个 Web 接口。例如,它不能支持独立的 GU
9、I 客户(中间层和这个 Web 接口在同一个 JVM 中)。但是,正如我们稍后将回看到的,可以增加一个 Web 服务层。 整个应用仅运行在单个 JVM 中。虽然这提高了性能,但我们无法将构件自由地分配给不同的物理服务器。 这种体系结构不能使用 EJB 容器事务支持。我们将需要在应用代码中创建和管理事务。 服务器没有提供对并发编程的支持。我们必须亲自处理线程化问题,或使用一个解决常见问题的类库,比如 util.concurrent。 将实体组件用于数据存取是不可能的,但可以证明的是,这根本不是什么损失。访问本地 EJB 的 Web 应用Servlet2.3 规范(SRV9.11)可从 http:
10、/ 站点上获得。如果一个应用被部署在一个集成的 J2EE 应用服务器中且该服务器运行在单个 JVM 中,该规范通过本地接口来保证 EJB 的 Web 层对象访问。这使我们技能从一个 EJB 容器中得到好处,又不至于招致过度的复杂性或把我们的应用变成分布式的。J2EE 体系结构4在这种体系结构中,Web 层与刚讨论过繁荣 Web 应用体系结构的 Web 层相同。业务接口也是相同的;这两种体系结构的不同之处从它们的出现(EJB 层)开始。因此,中间层被划分成了两部分(运行在 Web 容器中的业务接口和EJB),但这两部分运行在同一个 JVM 中。有两种方法可以用来实现业务接口: 代理方法。在这种方
11、法中,一个本地 EJB 直接实现业务接口,而 Web 容器代码被赋予一个对该 EJB 的本地接口的引用,同时无需处理必不可少的JNDI 查找。 业务委托方法。在这种方法中,业务接口的 Web 容器实现明确地托付给相应的 EJB。这具有允许高速缓存和允许故障操作在适当地点被重试的优点。我们无需担心上述任一情况中的 java.rmi.RemoteException 捕获。传输错误不会出现。在这种体系结构中,和通过 EJB 来暴露一个远程接口的体系结构不同,EJB的使用仅仅是这种体系结构的一个实现选择而已,而不是一个基本特征。不用改变总体设计,也不用 EJB,就可以实现任何一个业务接口。长处这种体系
12、结构具有如下这些优点: 它没有分布式 EJB 应用那么复杂。 EJB 使用不更改应用的基本设计。在这种体系结构中,只使这样一些对象成为 EJB:它们需要一个 EJB 容器的那些服务。 EJB 使用只强加相当小的性能开销,因为没有远程方法调用或串行化。 它提供 EJB 容器事务与线程管理的各种好处。 如果需要,它允许我们使用实体组件。弱点这种体系结构的缺点有如下这些: 它比纯 Web 应用更复杂。例如,它遇到 EJB 部署和类装人复杂性。 它仍不能支持除一个 Web 接口之外的客户,除非我们添加一个 Web 服务层。 整个应用仍运行在单个 JVM 中,这意味着所有构件都必须运行在同一台物理服务器
13、上。 具有本地接口的 EJB 测试起来很困难。我们需要在 J2EE 服务器内运行测试案例(比如用服务器小程序)。 作为使用 EJB 的结果,仍存在一些调整对象设计的诱惑,即使含有本地接J2EE 体系结构5口,EJB 调用仍慢于普通的方法调用,而且这可能会诱惑我们修改业务对象的自然粒度。有时,我们可能会决定把 EJB 引进到一个没有适应它的体系结构中。这可能是由“做可能管用的最简单事情”的 XP 方法所造成的。例如,最初的需求可能没有证明由 EJB 引入的复杂性是值得的,但后来增加的需求可能会提出使用EJB。如果采用上面描述的业务构件接口方法,引进具有本地接口的 EJB 将不会引起问题。可以简单
14、地选择应该被实现成具有本地的代理 EJB 的那些业务构件接口。引进具有远程接口的 EJB 可能有较大疑问,因为这不仅仅是一个引进 EJB的问题,而且也是一个从根本上改变了应用的性质的问题。例如,可能需要使业务接口粒度变的更粗,以避免“罗嗦的”调用和实现足够的性能。我们还可能需要把所有业务逻辑实现转移到 EJB 容器内部。分布式体系结构下面这两种体系结构除了支持 Web 应用之外,还支持远程客户。具有远程 EJB 的分布式应用这种体系结构被广泛地看做“经典的”J2EE 体系结构。它提供了这样一种能力:通过给 EJB 及使用 EJB 的构件(比如 Web 构件)使用不同的 JVM 来物理和逻辑地划
15、分中间层。这是一个复杂的体系结构,并具有显著的性能开销。虽然描述了一个 Web 应用,但该体系结构可以支持任一 J2EE 客户类型。它特别符合独立客户应用的需要。该体系结构在 UI 层(或者说其他远程客户)与业务对象之间使用 RMI,而这些业务对象被暴露为 WJB(RMI 通信的细节由 EJB 容器来隐藏,但我们仍需要处理使用它所带来的影响)。这使远程调用变成了一个主要的性能决定要素和一个核心的设计考虑因素。我们必须尽量最大限度的减少远程调用的数量(避免“罗嗦的”调用)。在 EJB 与 EJB 客户层之间传递的所有对象都必须是可串行化的,而且我们必须处理更复杂的错误处理需求。该体系结构中的 W
16、EB 层和上面所讨论的那些结构中的 WEB 层相同。但是,业务接口的实现将处理对(可能是远程)EJB 容器中的 EJB 的远程访问。在已讨论过的用于本地 EJB 的两种连通性方法(代理和业务委托)中,只有业务委托在这里是有用的,因为 EJB 远程接口上的所有方法都抛出JAVAX。RMI。REMOTEEXCEPTION。这是一个已检查异常,否则 REMOTEEXCEPTION将需要在 UI 层代码中被捕获。这把它不正确地束缚到了一个 EJB 实现上。EJB 层将单独负责与 EIS 层资源的通信,而且应该含有应用的业务逻辑。J2EE 体系结构6长处这种通信结构具有如下这些特有的优点 它可以通过提供
17、一个共享的中间层来支持所有 J2EE 客户类型 它允许应用构件在不同物理服务器上的分布。如果 EJB 层是无状态,这个特点特别管用,进而允许使用无状态的会话 EJB。含有有状态 UI 层和无状态中间层的应用将会从这种部署选择中获得最大的好处,而且将会给 J2EE应用实现尽可能大的缩放性。弱点这种体系结构的弱点有如下这些: 这是我们已讨论过的最复杂的方法,如果这种复杂性确定是业务需求的合理要求,很可能会导致整个项目周期内的资源浪费,并为故障提供一个滋生地。 它影响性能。远程方法调用会比使用引用的本地调用慢数百倍,总体性能方面的影响结果取决与必须的远程调用数量。 分布式应用的测试和测试变得很困难。
18、 所有业务构件都必须进行 EJB 容器中。虽然这为远程客户提供了一个综合性接口,但如果 EJB 不能用来解决业务需求所引起的每个问题,这是有问题的。例如,如果 SIN-GLETON 设计模式完全适用,用 EJB 满意地实现起来将会很困难。 OO 设计被 RMI 的集中使用所严重阻碍。 异常处理在分布式系统中变得更复杂。我们除了必须考虑应用故障外,还必须兼顾传输故障。当使用这种体系结构,千万不要破坏它。SUN JAVA CENTER 的“FAST LANE READER”J2EE 模式主张从 WEB 层中执行只读 JDBC 访问,以便最小化通过 EJB层进行调用的系统开销。这违背了每个层只应该跟
19、直接位于它下面的那些层进行通信的原则,也降低了缝补式体系结构的一个重要优点;部署灵活性。现在,运行 WEB 层的服务器必须能够访问数据库,而这会使特殊的防火墙规则车工内为必须之物。即使我们使用了远程接口,如果 EJB 及使用 EJB 的构件被放在了一起,那么大多数 J2EEE 服务器仍能优化远程调用并替换按引用的调用。这可以极大地减少使用具有远程接口的 EJB 所造成的性能影响,但无法消除远程语义所因如的有害影响。这种配置更改了应用的语句。要想让这种配置得到使用,关键是保证 EJB 支持本地调用(按引用)和远程调用(按值)。否则按引用的调用者可能会修改要传递其他调用者的对象,进而产生严重的后果。J2EE 体系结构7不要因为使用了具有远程借口的 EJB 导致一个应用变成分布式的,除非业务需求明确指出需要一个分布式体系结构。J2EE Architectures1