UML软件工程组织

 

 

Spring 2.0.1与BEA WebLogic Server 9.2的集成
 
作者:Andy Piper, Chris Wall, Eric Hsiao, Rod Johnson 出处:dev2dev.bea.com.cn
 

编辑注:Spring 2.0.2软件包于本文完成后已经发布了,现在可以从这里下载

摘要

一年多以前,我们讲述过 Spring 1.2.x与WebLogic Server 9.2的集成。其后,我们又验证了Spring和BEA WebLogic Server的更新的版本,一直到WebLogic Server 9.2和Spring 2.0的组合。这些版本表现出在功能性、可用性和性能上的重大飞跃,因此我们决定对文章进行更新以反映这一变化。

BEA WebLogic Server 9.2是Sun Microsystems的Java EE 1.4平台的领先实现。然而,WebLogic Server的核心价值主张则体现在Java EE规范没有覆盖的领域——增强的管理、易用性、高可用性、可伸缩性、可靠性和性能。实际上,WebLogic Server的价值不依赖于任何特定的编程模型,所以它与新也自然适用于新出现的非Java EE的Java编程模型。近年来出现的最令人激动的事物莫过于基于反向控制(IoC)的模型,Spring Framework就是它的事实上的实现。本文介绍了Spring 2.0 Framework、WebLogic Server以及这两者的集成的新特性。我们会看到,整体大于部分之和。

文章结构

文章的前两节概述Spring、WebLogic Server和它们各自的特性。如果您熟悉Spring Framework,那么可以跳过第一节。如果您熟悉WebLogic Server,那么可以跳过第二节。本文主要目的是介绍这两种技术的集成,所以本文后续的部分都是讲述这一主题的。首先,我们分析MedRec—WebLogic Server上的一个示例程序——分别以它的原始的Java EE形式和使用Spring Framework重构后的形式。之后,是关于特定的集成点的一些细节。如果您打算在 WebLogic Server上开发Spring应用程序,那么,几乎可以肯定,这些细节会对您有所帮助。如果您只是想有个大致的概念,可以先阅读标题,内容留待以后再看。最后,我们展望了一些正在考虑中的未来开发工作。

Spring简介

本节,我们来简要地概述Spring Framework的特性,包括2.0版以来的一些新特性。

Spring是基于Rod Johnson在 Expert One-on-One J2EE Design and Development(Wrox, 2002)公布的代码的一个分层的Java/Java EE应用程序框架。Spring的存在是因为我们相信Java EE应该更容易使用,并且有可能创造更简单的Java EE开发方法而不会牺牲平台性能。

Spring支持灵活的Java EE开发,允许使用Plain Old Java Objects(一般称为 POJO)开发Java EE应用程序。

改进的Spring开发体验

Spring在其核心部分提供了一个易于配置、XML驱动的反向控制(IoC)容器。IoC基于所谓的“好莱坞原则”:“不要打电话过来,请等通知。”在这种模式中,通过容器而不是直接编程将Java对象间的关系注入应用程序中。有两种注入方式—构造函数注入和setter注入,具体取决于容器是通过其构造函数还是mutator方法将信息注入已创建的Java对象。

在Spring中,注入的属性——或到其他bean的引用——是通过一个XML文件进行配置的,这使得配置轻而易举。它耦合了另外一个AOP框架,允许非侵入性增加诸如事务处理和安全等属性,这意味着开发人员可以专注于创建业务解决方案,而不必忙于复杂的Java EE开发或配置。由于容器是非侵入性的,所以您不必担心业务代码会被特定于供应商(此处也包括Spring)的工件所污染。

Spring应用程序组件

如上所述,Spring提供了一个轻量级的容器,用于提供集中式、自动化的配置并连接应用程序对象。它是非侵入性的,能够以一致的和透明的方式通过IoC把一组松耦合的组件(POJO)组装成复杂的系统。因为该容器允许首先独立地开发和测试各软件组件,然后在任意环境中(Java SE或Java EE)中进行扩展部署,所以它具有灵活性和高利用率,并提高了应用程序的可测试性和可伸缩性.此外,Spring提供了许多其他对开发人员友好的特性,下面我们一一列举:

  • 一个用于事务管理的通用抽象层:支持可插入的事务管理器,使事务划分更轻松,同时无需处理底层的问题。该层中还包括JTA策略和一个JDBC DataSource。相比普通的JTA或EJB CMT,Spring的事务支持不依赖于Java EE环境。考虑到是一个十分灵活的非侵入性解决方案,事务语义通过AOP应用于 POJO,通过XML或Java SE 5注释进行配置。
  • 一个JDBC抽象层:提供了一个有意义的异常层次结构(不再从SQLException抽取供应商代码),简化了错误处理,极大地减少了代码编写量。无需为了再次使用JDBC编写另外的finally代码块。面向JDBC的异常遵循Spring的一般DAO异常层次结构。
  • 与业界领先的对象——关系映射解决方案的集成:在资源拥有者、DAO实现支持和事务策略方面。对大量IoC便利特性的一流支持,解决了许多典型的O-R映射集成问题。所有这些都遵循Spring的一般事务和DAO异常层次。而且,Spring 2.0提供了与Java Persistence API (JPA)的完全集成。
  • AOP功能性:完全集成到Spring配置管理中。您可以对Spring所管理的任何对象启用AOP,增加了声明性事务管理等方面。借助于Spring,您能够拥有没有EJB的声明性事务管理——甚至也可以没有JTA。
  • 一个灵活的MVC Web应用程序框架:构建在核心的Sping功能之上。它是通过策略接口高度可配置的,并且适用多种视图技术,如JSP、Velocity、Tiles、iText和POI。注意,Spring中间层能容易地与基于任何其他Web MVC框架(如Struts、WebWork或Tapestry)的Web层组合。
  • 一个用户可扩展的配置层:允许用户在vanilla Spring配置中加入自己定制的XML标签。整个Spring 2.0核心库已经广泛地使用这一功能,提供增强的语法和通用Spring特性的可用性。
  • 异步编程抽象:包括与JMS提供者的框架中立的事务集成的消息驱动POJO(MDP);与异步调度机制的集成,如commonj、Java SE并行程序和Quartz;本地事件支持。

所有的Spring功能都可以在任何Java EE服务器上使用,大部分功能可以在非托管环境中使用。Spring的一个重心是支持可重用业务和不依赖于特定的Java EE 服务的数据访问对象。这些对象可以不费事地跨J2EE环境(Web或EJB)、独立应用程序和测试环境进行重用。

Spring的分层架构提供了大量灵活性。它的功能都构建在较低的层次上。例如,您可以在不使用MVC框架或没有AOP支持的情况下使用JavaBean配置管理。但是,如果您要使用Web MVC框架或AOP支持,您会发现它们构建在配置框架之上,所以您可以马上用上有关它的知识。

BEA WebLogic Server 9.2简介

本节,我们来简要概述BEA WebLogic Server的特性,重点强调其提供的底层基础架构,而不是编程模型。

WebLogic Server是可伸缩的企业级Java EE应用服务器。WebLogic Server基础架构支持各类分布式应用程序的部署,是构建各种应用程序的理想基础。

Sun Microsystem公司的 Java EE 1.4 规范 在WebLogic Server上的实现提供了标准的一组API,用以创建能够访问多种服务(如数据库、消息传递服务和外部企业系统连接)的分布式Java应用程序。终端用户客户程序使用Web浏览器客户端或Java客户端访问这些应用程序。由于Java EE是如此有名,这里我们就不进一步讨论了。参见关于 编程模型 的 WebLogic Server文档,可以获得更多信息。

除了实现Java EE之外,WebLogic Server还使企业能够在一个健壮的、安全的、高可用的、可伸缩的环境中部署任务关键型应用程序。这些特性允许企业配置WebLogic Server实例集群以分布负载,并在发生硬件或其他故障时提供额外的容量。新的诊断工具允许系统管理员监控和调优已部署的应用程序和 WebLogic Server环境本身的性能。可以对WebLogic Server进行配置来自动监控和调整应用程序吞吐量,无需人工干预。广泛的安全特性保护了服务的访问,保证了企业数据安全,并阻止了恶意攻击。

WebLogic Server的增强后的服务质量

就像许多其他的BEA产品,WebLogic Server如同冰山,浮在水面上的只是很少的一部分而已。具体来说,WebLogic Server提供了许多特性和工具来支持高可用的和可伸缩的应用程序部署:

  • WebLogic Server clusters 通过将工作负载分布到多个WebLogic Server实例之间,为用户的应用程序提供可伸缩性和可靠性。基于要处理的工作量,传入的请求能够被发送给集群中的一个WebLogic Server实例。万一出现硬件或其他故障,会话状态对其他集群节点可用,这些节点能够恢复故障节点的工作。另外,可以实现集群,使服务驻留在这样的单台机器上:如果出现故障,该机器可以选择把服务迁移到集群中的另一个节点上。
  • 除了在一个集群内跨服务器复制HTTP会话状态之外,WebLogic Server也能够 跨多个集群复制HTTP会话状态,从而在多个地理区域、多个网格和Internet服务提供商中扩展可用性和容错能力。
  • Work Manager 基于用户定义的规则对工作划分优先级,并监控实际的运行时性能统计信息。然后利用这些信息优化应用程序的性能。Work Manager可以全局地应用于一个WebLogic Server域或者一个特定的应用程序组件。
  • 过载保护 使WebLogic Server能够检测和避免过载情况,并从中得以恢复正常。
  • 网络频道 基于流量类型把网络流量分散到各个频道中去,有利于网络资源的有效使用。
  • WebLogic Server持久性存储 是一个性能卓越的内置存储器解决方案,用于需要持久性存储的WebLogic Server子系统和服务。例如,它可以保存持久性的JMS消息,或者暂时保存使用存储-转发特性发送的消息。持久性存储支持到基于文件的存储器或到支持JDBC的数据库的持久性。
  • 存储-转发服务 使WebLogic Server在跨 WebLogic Server实例分布的应用程序之间可靠地传递消息。如果由于网络或系统故障造成消息接受方无效,那么一个本地服务器实例将保存消息,并且当接受方有效时进行转发。
  • 企业级就绪部署工具 使应用程序从开发阶段到生产环境的部署和迁移变得容易。
  • 生产环境重新部署 使企业在不中断旧版程序的工作进程的情况下部署其新的版本。

现在,让我们来看一看这两个系统之间的协作。

在Java EE和Spring环境中开发应用程序

为了比较和对照Java EE和Spring开发方法的不同,我们采用用Spring 2.0 Framework重新编写了MedRec示例程序,充分利用Spring 2.0的许多创新特性。下一节,我们将给出MedRec一般架构的简短概述,然后依次看一下它的Java EE形式和Spring形式。

Medical Records应用程序

Avitek Medical Records(或MedRec)是一个WebLogic Server示例程序工具包,简明地示范了Java EE平台的各个方面。设计MedRec的目的是作为各层次水平Java EE开发人员的一个教学工具。它显示了每个Java EE组件的使用方法,阐明了适于组件交互和客户端开发的设计模式。MedRec也表明了在WebLogic Server上开发和部署应用程序的最佳实践。

MedRec背后的真实世界概念是一个框架,其中患者、医生、管理人员使用各种不同的客户端管理患者数据。对于患者,MedRec提供了基于Web的应用程序,供他们察看自己的医疗记录和维护档案文件。对于管理人员,MedRec提供了基于Web的应用程序,用于管理注册登记、医疗记录上传和所有应用程序监控。MedRec还提供与独立的医疗机构接合的资源。为了演示这个通信系统,MedRec包括一个医生应用程序,用于向MedRec系统请求和提交数据。

MedRec Java EE版本架构概述

Java EE和WebLogic Server版的MedRec的设计和实现采用传统的三层架构模型,分为相互独立的客户端、服务器和数据存储三个部分:

  • 表示层:它负责所有的用户交互;有时也称为客户端层。
  • 服务层:它是封装了应用程序业务逻辑的中间层。它处理来自异构客户端的请求,同时与各种后端系统进行交互,包括数据存储器。该层有时也称为服务器层。
  • 企业信息系统(EIS)层:它表示那些提供和/或存储遗留的程序和数据库的数据的系统。有时也称为数据存储。

我们为MedRec的患者和管理部门程序开发了Web应用程序(webapp),公开对于各自用户的服务。webapp符合模型-视图-控制器(Model-View-Controller)模式,Java Server Page呈现视图给用户,模型封装要呈现给用户和从用户处捕捉而来的数据,而控制器机制则管理除与服务层的交互之外的组件交互。MedRec采用Jakarta Struts来实现该模式。

服务层提供服务给发出请求的客户端,并管理与后端应用程序和资源的交互。MedRec的服务层采用Session Facade模式来封装业务逻辑和业务数据。Session Facade通过提供一个到分布式服务的接口,简化了应用程序的复杂性。在MedRec中,Session Facade的首要责任是提供数据吞吐量。在MedRec的J2EE和WebLogic Server版本中,Session Facade被开发为无状态的会话Enterprise JavaBean,而数据则是由实体Enterprise JavaBean来管理的。

为了与外部实体接合,MedRec通过Web服务公开应用程序功能,从而允许不同系统之间使用一系列开放标准动态交互。通过Web 服务公开服务使得MedRec能够为独立的各方提供数据,或接收来自各方的数据,这样就实现了集中式医疗记录管理的主要目标。

图1所示为Java EE和WebLogic版MedRec的高级架构示意图。

Spring 2.0.1与BEA WebLogic  Server 9.2的集成 图-1

图1:Java EE和WebLogic版MedRec架构示意图

使用Spring重新表示MedRec

为了使Spring能够利用WebLogic Server的企业级特性,我们重新设计了MedRec的架构,以相应的Spring组件替换核心Java EE组件。基于Spring的MedRec版本(MedRec-Spring)复制了与原版MedRec相同的功能。

反向控制

MedRec-Spring的最显著的变化是引入了Spring IoC。IoC方法功能强大,通过一个容器将依赖性注入到配置好的组件注入中而应用。IoC解耦了应用程序代码和它的配置。例如,对象与它们的依赖性无关,因此,可以专注于其职责。对于MedRec-Spring中,诸如DataSource、JMS 服务、MBean 连接和对等服务等企业资源在运行时被提供给 MedRec-Spring的对象。另外,通过迁移资源配置和在已编译代码外进行引用,应用程序从特定于开发的资源向中间的生产资源和环境的转移更加易于管理。

我们发现,要正确使用IoC,应用程序代码需要遵循更严格的Java编程规则——特别是在编写接口的代码时。接口比其他东西更能促进更好的协作,因为可以减轻依赖性,而且实现的变化被隔离开来。从IoC的角度看,接口支持依赖注入的可插入本性。为了利用IoC,我们对MedRec-Spring进行了重构,这样就可以基于接口对业务对象进行编码。

POJO

在MedRec-Spring中,Plain Old Java Objects(POJO)代替了无状态会话 EJB。无状态会话 EJB的强大在于它们的远程控制和事务管理功能。因为MedRec-Spring通过Spring的HTTP Invoker架构公开了服务bean,所以它能够满足远程控制的要求。事务管理是由Spring的事务抽象层提供的。MedRec-Spring的事务管理精确地映射了MedRec的事务管理,因为Spring事务管理器被配置为把责任委托给WebLogic Server的JTA事务管理器。

消息收发

MedRec-Spring包含了原始MedRec的大多数消息收发功能。采用Spring的 JMS包简化了一些一般性任务,如连接工厂和目的站查找。Spring提供了一个代表消息收发目的站的对象,而不是通过程序获取队列句柄。和所有的Spring beans一样,这些对象表示(JNDI名称、连接工厂关联等)是在已编译代码的外部配置的。。我们还在三个方面使用了Spring 2.0的 Message-Driven POJO(MDP)作为JMS消息的目标:

  • 邮件消息处理(向患者发送批准邮件或拒绝邮件。)
  • 注册消息处理(处理新患者注册)
  • 医疗记录上载处理(从XML文件向RDBMS上载医疗记录)

AOP

MedRec-Spring使用Spring AOP主要有两个目的:

  • 声明性事务管理
  • DAO实现后处理(JPA)的返回值

JPA

现在MedRec-Spring使用JPA访问和写入患者纪录。更多细节请见 结合SPRING 2.0使用JAVA PERSISTENCE API

应用程序管理

MedRec-Spring包含应用程序管理特性。这些特性与WebLogic Server的域配置以及运行时域交互。MedRec-Spring必须按照WebLogic Server的 MBean Server形式,Spring提供了连接管理,简化了MBean Server的可访问性。

Web Services

最后,MedRec-Spring使用Web services输出它的服务。Spring提供一个JAX-RPC 工厂生成Web服务的代理。类似于其他Spring bean,工厂bean也是在已编译的代码外部配置的,使得应用程序更加灵活。

图2所示为基于Spring的MedRec版本的高级架构示意图。

Spring 2.0.1与BEA WebLogic  Server 9.2的集成 图-2

  图2. 基于Spring的MedRec版本的高级架构图

WebLogic Server上的Spring最佳实践

比较了Java EE与Spring环境上的MedRec架构之后,现在我们来介绍在实现MedRec-Spring应用程序过程中发现的一些宝贵经验:

  • 使用延迟初始化。为了实现 IoC容器,Spring加载一个application context文件,创建并缓存每个已配置的bean实例。Spring bean引用的每个资源都必须可以实例化或查找,了解这一点很重要。例如,Spring的JMX支持提供到WebLogic Server的 MBean 服务器的连接。部署期间,不是所有的MBean server都是激活的,所以当部署资源的时候,应该在一启动使用Spring延迟初始化和查找服务。
  • 基于功能分离出Spring配置。这允许应用程序组件仅加载那些任务相关的上下文。这一实践也允许测试人员用一个特定于测试环境的上下文替换一个应用程序上下文(例如DataSource配置),从而来改变其行为。
  • 通过JndiObjectFactoryBean封装 JDBC DataSource连接入池。则那些要求数据库交互的Bean可以引用它,以便利用 WebLogic Server的DataSource 入池功能。
  • 为会话和消息驱动Enterprise JavaBeans使用Spring org.springframework.ejb.support。Spring org.springframework.ejb.support提供Enterprise JavaBeans(EJB)可以扩展的抽象类。这些抽象的EJB类通过包含EJB生命周期方法的标准实现来辅助开发。更重要的是,这些类提供了加载Spring应用程序上下文的机制,包括跨多个EJB和客户端共享上下文,因此在EJB初始化时减少了复制和负载。
  • 使用热部署和WebLogic Server的 拆分开发目录环境。这极大地改进了集成测试期间的Spring开发体验。 热部署允许应用程序重新加载,而无需重启服务器。拆分开发目录环境减少了不必要的文件复制,加快了开发和部署。拆分开发目录Ant任务帮助用户快速地重新编译和部署应用程序,无需首先生成一个可部署的存档文件或展开的存档目录。
  • 把Spring库打包为 应用程序库、可选扩展 或服务器扩展。这允许几个Spring应用程序共享Spring Framework,减少了应用程序的内存占用。不仅内存的占用减少了,而且提高了部署次数。

Spring on WebLogic Server工具包

为了帮助用户从部署在WebLogic Server上的Spring应用程序得到最大的收获,我们已经发布了一个经过认证的BEA发行版,包括Spring 2.0、MedRec on Spring应用程序和其他的一些不错的工具。您可以从BEA 的 发行版Web站点 上免费下载这个工具包。

企业Spring

Spring Framework的非侵入性IoC开发模型不但依赖于Java EE应用服务器可用的特性集,而在旨在补充该特性集。事实上,在要求很高的生产环境中,底层应用服务器基础架构提供的服务质量对Spring应用程序的可靠性、可用性和性能非常重要。WebLogic Server 9.2提供了企业级的特性,能够从各方面增强用户的Spring应用程序。这一节,我们来详述这些特性以及如何在Spring应用程序中利用它们。

集群管理和部署

一个WebLogic Server集群包括多个WebLogic Server服务器实例,这些服务器实例同时运行并一起工作,从而提高了可伸缩性和可靠性。对客户端来说,集群就像单个的WebLogic Server实例一样。构成集群的服务器实例既可以运行在同一台机器上,也可以位于不同的机器上。可以通过在现有的机器上向集群添加另外的服务器实例,或者向集群添加机器以驻留增加的服务器实例,来提高集群的容量。WebLogic Server集群为Spring应用程序提供了一个企业级部署平台,WebLogic Server提供的丰富性和易用性是其他支持相似特性的技术所不具有的。关于WebLogic Server集群的配置和管理的完整讨论请见Understanding Cluster Configuration

通常,Spring应用程序被打包成 webapp形式,在这种情况下,无需为了应用WebLogic Server集群技术而更改自己的应用程序。只需将应用程序部署到集群中的服务器就可体验增强的可伸缩性和可用性带来的好处。

Spring会话复制

Spring Web应用程序通常将信息存入HTTP会话,如订单ID和用户信息。为了支持一个集群内的servlet和JSP的自动复制和故障恢复,WebLogic Server支持用于保持HTTP会话状态的 几种机制。简单地通过将用户应用程序提供给一个适当的weblogic.xml部署描述符,它们就能够被Spring Web applications非侵入性地使用。有关WebLogic Server 9.0的更多可用信息,请参见 配置不同的会话持久性

集群化的Spring远程控制

Spring提供强大的远程控制支持,允许用户仍然利用一致的基于POJO的编程模型轻松地导出和使用远程服务。通过一个接合到适当的Spring bean的RMI接口,Vanilla Spring支持代理POJO调用。然而,这种支持仅限于JRMP(Sun的RMI实现),或者通过JndiRmiProxyFactoryBean使用特定的远程接口。借助于Spring 1.2.5 on WebLogic Server 9.0认证,我们已经扩展了JndiRmiProxyFactoryBean和相关的服务导出程序——这样它就能支持任何J2EE RMI实现的POJO代理,包括RMI-IIOP和T3。这方面的支持还包括一个WebLogic RMI部署描述符,它支持代理RMI接口上的集群化,所以POJO调用可以跨一个WebLogic Server集群进行负载均衡。客户端上这种支持的配置与此相似(applicationContext.xml)。

<bean id="proProxy"
  class="org.springframework.remoting.rmi.JndiRmiProxyFactoryBean">
   <property name="jndiName" value="t3://${serverName}:${rmiPort}/order"/>
   </property>
   <property name="jndiEnvironment">
      <props>
         <prop key="java.naming.factory.url.pkgs"> 
               weblogic.jndi.factories
         </prop>
      </props>
   </property>
   <property name="serviceInterface"
       value="org.springframework.samples.jpetstore.domain.logic.OrderService"/>
</bean>

服务导出程序如下(同样来自applicationContext.xml):

<bean id="order-pro"   class="org.springframework.remoting.rmi.JndiRmiServiceExporter">
   <property name="service" ref="petStore"/>
   <property name="serviceInterface"
     value="org.springframework.samples.jpetstore.domain.logic.OrderService"/>
   <property name="jndiName" value="order"/>
</bean>

集群化的描述符是自动包含在内的,仅仅要求适当的集群配置和Spring应用程序在所有集群成员上部署。参见 故障恢复支持,可以获得更多信息。

对Spring组件的控制台支持

Spring on WebLogic Server工具包中包含一个WebLogic Server控制台扩展,它显示了应用程序中定义的Spring bean、属性和操作。它构建在WebLogic控制台扩展门户框架之上,这一框架能够变换WebLogic Administration控制台的外观、功能和布局,而无需修改服务器或控制台代码。将控制台扩展复制到yourdomain/console-ext目录下,则重新启动服务器时就部署了控制台扩展。关于部署控制台扩展的更多细节,请参考Spring on WebLogic Server工具包。

控制台扩展为不是MBean的Spring bean自动创建(JMX)管理接口(对于多数Spring beans,通常就是这样),通过在applicationContext.xml中配置一个MBeanExporter并指定经汇编器公开的bean来完成。这一特性是Spring和WebLogic Server无缝地、非侵入性协作的一个极好的例证。为了使Spring应用程序支持JMX,只需要更改以应用程序上下文部署描述符。为了使控制台支持Spring,只需要将两个jar部署到已有域即可。

为了在WebLogic Server Administration控制台启动Spring Console扩展,需要两个jar文件;它们作为Spring WebLogic包的一部分提供。具体来说,这两个jar文件称为spring-ext-server.jar和spring-ext-client.jar。spring-ext-server.jar需要复制到yourdomain/console-ext目录。相关的spring-ext-client.jar文件需要和 Web应用程序一道部署。(如果是.WAR文件,则将spring-ext-client.jar放入Web应用程序的 WEB-INF/lib目录。)

有了这两个文件后,剩下的工作就是在Spring XML配置文件中定义几个 bean。第一个Spring bean是绝对要定义的,它是com.interface21.wl9.jmx.mediator.Mediator。这个bean(顾名思义)介于用户应用程序、WebLogic Server的 MBeanServer和Administrative控制台三者之间。它的定义如下所示,非常简单:

<!-- WLS console adapter bean -->
<bean id="consoleAdapter" class="com.interface21.wl9.jmx.mediator.Mediator"/>

这个bean必须被“插入”(或说依赖性注入)第二个bean,即MBeanExporter,它也是绝对必须进行配置的。MBeanExporter 类交付的成果就是将Spring应用程序上下文中已定义的任何数量的异构bean简单地导出到BEA WebLogic MBeanServer(或者任何配置好的MBeanServer)。注意,MBeanServer导出的那些bean无需为JMX而进行编码。Spring JMX基础架构代码负责生成ModelMBean来描述通过JMX的用于管理而导出的bean。下面是一个典型的上下文配置文件的MBeanExporter bean定义:

<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
  <property name="assembler" ref="assembler"/>
  <property name="server" ref="server"/>
  <property name="beans">
    <map>
      <!-- these are the beans that are to be exported... -->
      <entry key="my_app_name:type=MaintenanceControl" 
             value-ref="maintenanceInterceptor"/>
      <entry key="my_app_name:type=ExceptionMonitor" 
             value-ref="exceptionHandler"/>
      <entry key="my_app_name:type=RequestStatistics" 
             value-ref="requestStatisticsFilter"/>
    </map>
  </property>
  <property name="registrationBehaviorName" 
            value="REGISTRATION_REPLACE_EXISTING"/>
  <property name="autodetect" value="true"/>
  <property name="listeners">
   <list>
    <!-- notice how we 'plug-in' the Mediator bean
           that was defined previously... -->
    <ref bean="consoleAdapter"/>
   </list>
  </property>
</bean>

注意上面的bean定义,另一个bean('assembler')被注入MBeanExporter的 'assembler'属性。下面是它的定义:

<bean id="assembler" class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler">
 <property name="interfaceMappings">
   <props>
    <prop key="my_app_name:type=MaintenanceControl">fully.qualified.management.interface.name</prop>
    <prop key="my_app_name:type=ExceptionMonitor">fully.qualified.management.interface.name</prop>
    <prop key="my_app_name:type=RequestStatistics">fully.qualified.management.interface.name</prop>
   </props>
 </property>
</bean>

描述Spring JMX提供的所有内容超出了本文的范围。这样说就够了:上面定义的InterfaceBasedMBeanInfoAssembler bean是一个可能的策略,用以控制用户bean的哪些方法和属性实际地公开出来供管理之用,就像JMX操作和属性那样。InterfaceBasedMBeanInfoAssembler使用(任意地)接口决定公开哪些方法和属性。更多信息请查本文最后的参考资料一节。

记录在MBeanExporter的bean定义上的第二个属性是server属性。这是向MBeanExporter注入一个WebLogic Server的 MBeanServer实例的地方。MBeanExporter将输出所有已配置的bean到这一指定的服务器。下面是这个bean的定义:

<!-- WebLogic 9 MBeanServer -->
<jndi:jndi-lookup id="server" jndi-name="java:comp/env/jmx/runtime"/>

在server bean的这个定义中,实际上MBeanServer实例源自JNDI(使用为jndiName属性指定的值在上下文中查找)。对于MBeanExporter,MBeanServer源自JNDI的事实没有意义;这个将依赖性注入需要依赖性的对象透明源引是依赖性注入方法的一大附加值(上面所见的易于使用和配置的JndiObjectFactoryBean证明Spring的注入支持是非常高级的)。

最后,最有趣的是,MBeanExporter配置的一部分是beans属性。它是一个(JMX) ObjectNames到bean的一个简单映射,这些bean将导出到先前注入的MBeanServer实例以便管理。选择ObjectName的策略(在这种策略下,您的bean实际上会导出到MBeanServer)是完全可配置的。本例中,所用的缺省策略是简单地使用beans 映射的键作为ObjectName。(见JavaDoc,它是随Spring一起提供的,作为各种ObjectName策略的一个全面纲要。)

Web services支持

Spring 远程控制功能的另一个方面是它对RPC风格的 Web services的支持。WebLogic Server提供了基于Ant的工具,来根据Web服务的描述生成JAX-RPC存根。Web服务客户端利用这些生成的存根获取一个表示服务器端操作的远程接口。Spring提供一个JaxRpcPortProxyFactoryBean简化了这个过程。

我们发现,在WebLogic Server环境中正确地配置JaxRpcPortProxyFactoryBean有些棘手,所以为了节约您的时间,我们给出下面这个代码片断,演示如何为一个包含复杂类型的Document Literal包装的Web服务配置代理生成。

多数属性是自解释的。有几个比较有名:

  • serviceInterface是Spring setter注入的副产品。这个类将表示Web services操作。
  • customProperties属性支持定制的WebLogic Server Web服务存根属性。
  • jaxRpcService值被设置为WebLogic Server的生成的JAX-RPC实现服务。JAX-RPC服务负责验证Web服务和加载复杂类型映射。为了实现后者,WebLogic Server的JAX-RPC实现服务必须配置为一个Spring bean。这保证了JAX-RPC服务构造函数的运行,而且类型映射文件也在此加载。

在JaxRpcPortProxyFactoryBean上设置lookupServiceOnStartup为false,即可在启动时关闭JAX-RPC服务查找。当首次访问时,将会进行查找。这对于与可靠的WebLogic Server请求/响应Web services通信是必须的,而此处的客户端也必须是一个Web服务。在这些情况下,始发客户端通常是与Web服务客户端一起部署的。因为应用程序部署完成前不会激活Web服务,所以对于Spring上下文加载,客户端Web服务是不可用的。如下代码摘录自一个applicationContext-ws.xml上下文配置文件:

<!-- reliable asynchronous Web service for sending new medical records to medrec -->
<bean id="reliableClientWebServicesPortType"
  class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean"
  lazy-init="true">
   <property name="wsdlDocumentUrl"
     value="http://${WS_HOST}:${WS_PORT}/ws_phys/PhysicianWebServices?WSDL"/>
   <property name="portName" value="PhysicianWebServicesPort"/>
   <property name="jaxRpcService">
      <ref bean="generatedReliableService"/>
   </property>
   <property name="serviceInterface"
     value="com.bea.physician.webservices.client.PhysicianWebServicesPortType"/>
   <property name="username" value="medrec_webservice_user"/>
   <property name="password" value="weblogic"/>
   <property name="customProperties">
      <props>
         <prop key="weblogic.wsee.complex">true</prop>
      </props>
   </property>
</bean>

<!-- allows the jaxRpcService class to execute its constructor which loads in type mappings -->
<bean id="generatedReliableService"
  class="com.bea.physician.webservices.client.PhysicianWebServices_Impl">
</bean>

参见WebLogic Server的 Overview Web Services Invocation Remoting and Web Services Using Spring,可以获得更多相关信息。

安全性

WebLogic Server安全系统支持并扩展了Java EE的安全性,提供了一组丰富的安全提供程序,可以对其进行定制,来处理不同的安全性数据库或安全性策略。除了使用标准的Java EE安全性之外,应用程序编程人员还能够使用很多专有扩展,这些扩展使应用程序可以与安全系统紧密集成。WebLogic Server带有几个安全提供程序,例如,可以选择包含大部分流行LDAP服务器的身份验证数据库、Active Directory、本地Windows和一个内置的身份验证解决方案。可以使用定制的提供程序对内置的提供程序进行扩充,从而几乎可以与任意身份验证数据库、授权机制和凭证映射服务相集成。因为部署为webapp的Spring应用程序使用的是Java EE安全性,所以无需修改应用程序就可以获得WebLogic Server的安全性优点。

经验丰富的Spring用户还会熟悉Acegi——Spring自身的安全框架。目前,可以在应用程序中使用Acegi、WebLogic Server安全性,或同时使用二者,因为它们是相互独立的。稍后我们将讲述与此相关的更多信息。

分布式事务

Spring提供事务管理的基础架构。除了对各家数据库供应商的支持之外,Spring还通过一家 Java EE 供应商的JTA实现支持分布式事务。通过WebLogicJtaTransactionManager,可以把Spring的JTA管理器配置为与WebLogic Server的JTA实现一起工作。

WebLogicJtaTransactionManager直接向WebLogic Server Java Transaction API委托责任。通过JNDI,客户端和bean提供者可以使用WebLogic Server JTA TransactionManager接口,这一交互由Spring管理。事务管理器也支持事务的作用域;事务能够作用于集群和域的内部或二者之间。

WebLogicJtaTransactionManager最强大的特性是管理分布式事务的能力和用于企业应用程序的两阶段委托协议。使用WebLogicJtaTransactionManager,应用程序能够利用WebLogic Administration Console来进行事务监控。WebLogicJtaTransactionManager还支持按数据库隔离级别,允许复杂的事务处理配置。下面的代码节选自applicationContext-service.xml:

<bean id="serviceFacade" class="com.bea.medrec.web.service.ServiceFacadeImpl">
    <!-- .... -->
</bean>
<!-- spring's transaction manager delegates to WebLogic Server's transaction manager -->
<bean id="transactionManager" class="org.springframework.transaction.jta.WebLogicJtaTransactionManager">
<property name="transactionManagerName" value="javax.transaction.TransactionManager"/> </bean> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.bea.medrec.web.service.ServiceFacade.*(..))"/> </aop:config> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="activate*" propagation="REQUIRED"/> <tx:method name="deny*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="process*" propagation="REQUIRED"/> <tx:method name="get*" propagation="REQUIRED" read-only="true"/> <tx:method name="search*" propagation="REQUIRED" read-only="true"/> <tx:method name="saveRecord" propagation="REQUIRED"/> <!-- ... --> </tx:attributes> </tx:advice>

如需了解更多信息,请参见Overview of Transactions in WebLogic Server Applications 在Spring中实现事务挂起

消息驱动POJO

消息驱动POJO(MDP)替代了Java EE的消息驱动Bean(MDB)。与POJO类似,它们的优势也是不要求任何特定于平台的API扩展或scaffolding。仅仅需要标准的JMS API实现:

public class RegistrationMessageListener implements MessageListener {
    public void onMessage(Message message) {
        // Fetch Registration information from ObjectMessage.
        // Process new reg by invoking service (DI)
        // ...    }
}

与 Spring的大多数成员一样,MDP容器的配置当然也很简单。下面的代码节选自applicationContext-jms.xml:

<!-- JMS ConnectionFactory and Queue -->

<jndi:jndi-lookup id="jmsConnectionFactory" jndi-name="com.bea.medrec.messaging.MedRecQueueConnectionFactory"/>
<jndi:jndi-lookup id="registrationQueue" jndi-name="com.bea.medrec.messaging.RegistrationQueue"/>

<!-- MDP -->

<bean id="registrationMessageListener" class="com.bea.medrec.service.messaging.RegistrationMessageListener">
    <!-- ... properties... -->
</bean>

<!-- MDP container -->
<bean id="registrationMessageListenerContainer"

          class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="jmsConnectionFactory"/>
    <property name="concurrentConsumers" value="5"/>

    <property name="destination" ref="registrationQueue"/>
    <property name="messageListener" ref="registrationMessageListener"/>
    <property name="transactionManager" ref="transactionManager"/>

</bean>

关于在WebLogic Server上实现MDP的更多详细讨论请见 这里

JPA和AOP的配置

我们已经定义了一个Web服务层,它允许我们在RMI、Spring HTTP invoker、Hessian/Burlap和JAXPRC之间轻松切换Web服务实现。当调用远程服务时,如果想要使用一种可序列化机制传递对象,那么这些对象本身必须可序列化。遗憾的是,OpenJPA的 Find结果是一个私有的List实现,不支持Serializable,所以我们需要将这些List与一些更合适的List绑定,如Java SE集合库的ArrayList或LinkedList。我们可以使用spring aop,不必修改应用程序源代码:

@Aspect
public class ReturningValuePostProcessorAspect {
    @Pointcut("execution(java.util.List com.bea.medrec.dao.PatientDao.*(..))")
    public void postProcessPatientDao() {
    }

    @Pointcut("execution(java.util.List com.bea.medrec.dao.RecordDao.*(..))")
    public void postProcessRecordDao() {
    }

    @Pointcut("execution(java.util.List com.bea.medrec.dao.UserDao.*(..))")
    public void postProcessUserDao() {
    }
}

下面是相关联的ReturningValuePostProcessor类。

@Aspect
public class ReturningValuePostProcessor {
    public ReturningValuePostProcessor() {
    }

    @Around("com.bea.medrec.dao.jpa.ReturningValuePostProcessorAspect.postProcessPatientDao()")
    public Object postProcessPatientDao(ProceedingJoinPoint pjp) throws Throwable {
        return doPostProcess(pjp);
    }

    @Around("com.bea.medrec.dao.jpa.ReturningValuePostProcessorAspect.postProcessRecordDao()")
    public Object postProcessRecordDao(ProceedingJoinPoint pjp) throws Throwable {
        return doPostProcess(pjp);
    }

    @Around("com.bea.medrec.dao.jpa.ReturningValuePostProcessorAspect.postProcessUserDao()")
    public Object postProcessUserDao(ProceedingJoinPoint pjp) throws Throwable {
        return doPostProcess(pjp);
    }

    private Object doPostProcess(ProceedingJoinPoint pjp) throws Throwable {
        Object retVal = pjp.proceed();
        if (retVal == null) {
            return null;
        }
        if (!(retVal instanceof List)) {
            return retVal;
        } else {
            //noinspection unchecked
            return new ArrayList((List) retVal);
        }
    }
}

下面的代码节选自applicationContext-jpa.xml:

<bean id="patientDao" class="com.bea.medrec.dao.jpa.PatientDaoImpl"/>:

<bean id="recordDao" class="com.bea.medrec.dao.jpa.RecordDaoImpl"/>:
<!-- ... -->:
<bean id="returningValuePostProcessor" class="com.bea.medrec.dao.jpa.ReturningValuePostProcessor"/>:
<aop:aspectj-autoproxy/>:

Java Management Extension

Java Management Extension(Java管理扩展,JMX)是Java应用程序监控和管理规范。它允许一般的管理系统监控应用程序,挡应用程序需要注意时发出通知,并修改应用程序状态以补救问题。Spring提供广泛的JMX支持,包括通过Spring MBeanServerConnectionFactoryBean公开WebLogic Server的 MBeanServer的能力。MBeanServerConnectionFactoryBean是一个方便的工厂,附带一个MBeanServerConnection。在应用程序部署期间,连接建立并被缓存,以后由引用bean进行操作。

可以配置MBeanServerConnectionFactoryBean返回WebLogic Server的 Runtime MBean Server,公开特定的WebLogic Server实例的监视、运行时控制和活动配置。这包括访问WebLogic Server Diagnostics Framework。此外,Runtime MBean为当前服务器提供runtime MBean和活动配置MBean的访问。

还可以配置MBeanServerConnectionFactoryBean,获得到WebLogic Server的Domain Runtime MBean Server的连接。Domain Runtime MBean Server提供域范围内服务的访问,如应用程序部署、JMS服务器和JDBC数据源。它还是访问域中所有服务器的所有runtime MBean和活动配置MBean的层次结构的单点。这个MBean Server也是访问被管理服务器上的MBean的单点。

此外,可以配置MBeanServerConnectionFactoryBean获取与WebLogic Server的 Edit MBean Server的连接。Edit MBean Server提供管理当前WebLogic Server域配置的入口点。

注意,在部署期间,WebLogic Server的 Domain Runtime MBean Server不是活动的。所以,bean需要使用Spring的延迟初始化(lazy initialization)进行配置,它会在调用bean时获取该bean。

下面是使用WebLogic MBean Server配置Spring MBeanServerConnectionFactoryBean连接的一个例子:

<!-- expose WebLogic Server's runtime mbeanserver connection -->
<bean id="runtimeMbeanServerConnection"
  class="org.springframework.jmx.support.MBeanServerConnectionFactoryBean">
   <property name="serviceUrl"      value="service:jmx:t3://${WS_HOST}:${WS_PORT
}/jndi/weblogic.management.mbeanservers.runtime"/> <property name="environment"> <props> <prop key="java.naming.security.principal"> ${WS_USERNAME}</prop> <prop key="java.naming.security.credentials"> ${WS_PASSWORD}</prop> <prop key="jmx.remote.protocol.provider.pkgs"> weblogic.management.remote</prop> </props> </property> </bean>

如需获得更多信息,请参见 Understanding WebLogic Server MBeans 和Spring JMX Support

支持

从 WebLogic Server 9.0和Spring 1.2.5开始,BEA就为Spring Framework on WebLogic Server提供了支持和认证。这种支持不仅是测试WebLogic Server上的Spring库的健全性,还致力于BEA和Interface 21——Spring Framework的创建者和维护者之间的积极努力和协作。我们不但测试了上面所讲的Spring 2.0的所有特性和配置,一些新特性还是直接作为BEA和Interface 21的协作成果引入Spring 2.0的。

下载

Spring Open Source Framework Support 2.0 download 包括Spring 2.0(已在WebLogic Server 9.2上经过验证)和Spring-JMX控制台扩展以及利用Spring 2.0 Framework重新编写的WebLogic Medical Records示例程序。

未来的工作

今后,我们计划提供WebLogic Server和Spring Framework的更深层次的集成。我们有了一些想法,其中最令人感兴趣的是:

  • Spring部署单元:通常Spring应用程序被部署为webapp,今后为Spring应用程序提供专用部署单元是可能的。
  • Spring和WebLogic Server安全性集成:Spring安全措施是Spring安全框架,我们计划将它与WebLogic Server的企业级安全框架集成。

结束语

我们用了一些时间讨论了Spring、WebLogic Server和这两种技术的集成。如我们所展示的那样,WebLogic Server增强了应用程序的服务质量,Spring则提高了开发人员的生产力。这两种技术都是高度非侵入性的,允许您专注于应用程序的业务功能的开发,而不是纠缠于特定于技术的API的错综复杂性。

参考资料

原文出处:http://dev2dev.bea.com/pub/a/2007/04/spring-2-weblogic-server-9-integration.html

 

组织简介 | 联系我们 |   Copyright 2002 ®  UML软件工程组织 京ICP备10020922号

京公海网安备110108001071号