级别: 中级 Naveen Balani (naveenb@webifysolutions.com), 技术架构师, Webify Solutions
2005 年 11 月 07 日 快速了解使用 Spring JMS 框架和 IBM WebSphere MQ 5.3 进行 JMS 消息处理的基础知识。 在 Spring 系列 的第 4 期也是最后一期中,我将介绍 Spring JMS(Java 消息服务)框架的特性。JMS PG 定义了 Java 应用程序通过面向消息的中间件(MOM)创建和交换消息的标准途径。 就 像在这个系列前面的文章中一样,我将使用一个简单的示例来演示 Spring JMS 的特性。您将随我一道开发一个点对点的(P2P)基于消息的系统,使用 Spring JMS 框架通过 JMS 接口与 IBM 的 WebSphere MQ 集成。完成练习后,将可以通过这个系统发送和接收简单的文本消息。 在开始之前,请 下载文章的源代码。请参阅 参考资料 访问 Spring 框架和 IBM WebSphere MQ 5.3。还需要 Apache Ant 来运行示例应用程序。 Spring JMS Spring 的 JMS 抽象框架简化了 JMS API 的使用,并与 JMS 提供者(比如 IBM 的 WebSphere MQ 5.3)平滑地集成。org.springframework.jms.core 包提供了在 Spring 中使用 JMS 的核心功能。它的模板类处理资源的创建和释放,简化了 JMS 的使用。 像 其他大多数 Spring 模板类一样,JMS 模板类提供了执行公共操作的 helper 方法。在需要更复杂应用的情况下,类把处理任务的核心委托给用户实现的回调接口。JMS 类提供了方便的方法,用来发送消息、同步地使用消息以及向用户公开 JMS 会话和消息的制作者。 以下 JMS 包和 org.springframework.jms.core 一起构成了 Spring JMS 的功能: org.springframework.jms.support- 提供转换
JMSException 的功能。转换代码把检测到的 JMSException 层次结构转换成未检测到异常的镜像层次结构。 org.springframework.jms.support.converter- 提供
MessageConverter 抽象,以在 Java 对象和 JMS 消息之间进行转换。 org.springframework.jms.support.destination- 提供管理 JMS 目标的不同策略,比如针对 JNDI 中保存的目标的服务定位器。
org.springframework.jms.connection- 提供适合在独立应用程序中使用的
ConnectionFactory 实现。connection 还包含针对 JMS 的 Spring PlatformTransactionManager 实现。它允许把 JMS 作为事务性资源集成到 Spring 的事务管理机制中。
| 回页首 |
|
IBM WebSphere MQ 就 像前面提到的,示例应用程序会用 Spring 的 JMS 框架通过 JMS 接口与 IBM 的 WebSphere MQ 集成。通过在应用程序和 Web 服务之间传递消息,WebSphere MQ 提供了可靠的、有恢复能力的应用程序集成。它使用队列和事务性工具帮助保持消息跨网络的完整性。WebSphere MQ 降低了信息丢失的风险和调和通信 IT 系统的需要。 WebSphere MQ 在它所支持的所有平台上提供了一致的应用程序编程接口,这有助于让集成的程序可移植。除了标准接口外,WebSphere MQ 还完整实现了JMS 接口,包括对发布-订阅消息传递的支持。WebSphere MQ Explorer 工具可以远程地管理和配置整个 MQ 网络。管理和配置工具基于开放源码的 Eclipse 框架,而且是可扩展的。
| 回页首 |
|
Spring JMS 模板 Spring 框架提供了 JmsTemplate 的两个实现。JmsTemplate 类使用 JMS 1.1 API,子类 JmsTemplate102 则使用 JMS 1.0.2 API。我的示例应用程序使用的是 JmsTemplate102 。 JMS 模板被用来发送和接收 JMS 消息。Spring 采用回调机制对 JMS 信息传递进行协调。MessageCreator 回调接口用 JmsTemplate 中的调用代码提供的 Session 创建消息。为了支持 JMS API 更复杂的应用,回调 SessionCallback 向用户提供了 JMS 会话,而 callback ProducerCallback 则公开了 Session 和 MessageProducer 组合。 清单 1 显示了示例应用程序使用的 JMS 模板的配置。清单摘自 spring-mqseries-jms.xml 文件(请参阅 下载)。 清单 1. JMS 模板配置
class="org.springframework.jms.core.JmsTemplate102"> false 20000 |
jmsQueueTemplate bean 与 JMS 连接工厂和 JMS 目标解析器绑定在一起,用于解析 JMS 客户机通过 JNDI 提供的目标队列名。connectionFactory 属性指定了如何获得到 JMS 提供者的连接。在本例中,清单 2 显示了如何从 JNDI 检索连接工厂。 清单 2. 通过 JNDI 配置 JMS 连接工厂
class="org.springframework.jndi.JndiObjectFactoryBean"> MQ_JMS_MANAGER |
可以看到,JndiObjectFactoryBean 被绑定到 internalJmsQueueConnectionFactory 。JndiObjectFactoryBean 用 JndiTemplate 属性进行 JNDI 查询。Spring 将用 JndiTemplate 中指定的环境属性和初始上下文在 JNDI 中查询连接工厂。清单 3 显示了 JndiTemplate 配置 bean 的配置。 清单 3. JNDI 查询的 JNDI 模板配置
com.sun.jndi.fscontext.RefFSContextFactory file:/C:/JNDI-Directory |
以上配置进行 JNDI 查询时用 com.sun.jndi.fscontext.RefFSContextFactory 指定初始上下文工厂,用基于文件的 file:/C:/JNDI-Directory 作为提供者 URL。根据示例应用程序的意图,JNDI 访问会采用基于文件的 FSContext 版本(请参阅 参考资料)的配置把 MQ 队列绑定到 JNDI。 有了定义好的 JMS 模板,下一步就是把它绑定到示例应用程序中,然后就可以用它发送和接收消息了。
| 回页首 |
|
Spring JMS 实现 JMS 模板可以绑定到应用程序中,以发送和接收 JMS 消息。在清单 4 中可以看出我如何把 清单 1 中的 JMS 模板绑定到示例应用程序中。 清单 4. 把 JmsTemplate 绑定到应用程序中
class="springexample.client.JMSSender"> class="springexample.client.JMSReceiver"> |
可以看到,我把 jmsQueueTemplate 绑定到用来发送和接收消息的 JmsSender 应用程序 bean 和 JmsReceiver bean。清单 5 显示了与 JMSSender 类有关的代码。 清单 5. 用 JmsTemplate 发送 JMS 消息的 JMSSender
public class JMSSender { private JmsTemplate102 jmsTemplate102; public JmsTemplate102 getJmsTemplate102() { return jmsTemplate102; } public void setJmsTemplate102(JmsTemplate102 jmsTemplate102) { this.jmsTemplate102 = jmsTemplate102; } public void sendMesage(){ jmsTemplate102.send("JMS_RequestResponseQueue", new MessageCreator() { public Message createMessage(Session session) throws JMSException { return session.createTextMessage("This is a sample message"); } }); } |
JMSSender 类用 jmsTemplate102.send() 方法发送 JMS 消息。send() 方法的第一个参数是 JNDI 队列名,队列名指定了消息应当发送到哪里。(很快就会看到如何把 WebSphere MQ 的队列名绑定到 JNDI。)send() 方法的第二个参数是 MessageCreator 类。JmsTemplate 中的调用代码提供了 Session 类,这个类提供了一个创建 JMS 消息的回调接口。 下一步是用 JMS 的 Session 类创建一个简单的文本消息。在代码执行时,消息会传递给 WebSphere MQ 服务器的队列。清单 6 显示了使用 JmsTemplate 检索 JMS 消息的 JMSReceiver 应用程序 bean 的代码。 清单 6. 用 JmsTemplate 检索 JMS 消息的 JMSReceiver
public class JMSReceiver { private JmsTemplate102 jmsTemplate102; public JmsTemplate102 getJmsTemplate102() { return jmsTemplate102; } public void setJmsTemplate102(JmsTemplate102 jmsTemplate102) { this.jmsTemplate102 = jmsTemplate102; } public void processMessage(){ Message msg = jmsTemplate102.receive("JMS_RequestResponseQueue"); try{ TextMessage textMessage = (TextMessage) msg; if( msg!=null){ System.out.println(" Message Received -->" + textMessage.getText()); } }catch(Exception e){ e.printStackTrace(); } } } |
JMSReceiver 类用 jmsTemplate102.receive() 方法同步地接收 JMS 消息。receive() 方法指定 JNDI 队列名,并从中检索消息。JMSTemplate 类的 processMessage() 方法由接收 JMS 客户机调用。JSMTemplate bean 的属性 receiveTimeout(列在 JMSTemplate 配置中)指定接收客户机同步地从队列中接收消息时要等候的时间。 现在应用程序的代码已完成!下一步就是配置 WebSphere MQ 队列并把它们绑定到 JNDI 对象。
| 回页首 |
|
队列管理器的设置 在运行应用程序之前,需要设置 WebSphere MQ 的队列管理器和队列,并把它们绑定到 JNDI。如果喜欢的话,可以按照这部分的示例做:只需 下载 设置 WebSphere MQ 队列的批文件和应用程序的源代码和部署描述符即可。把 zip 文件解压到驱动器 C:。 设置队列 运行 C:/SpringSeriesPart4JMS/batch 文件夹中的 mqsetup.bat 文件。这个批文件要求在 path 环境变量中设置好 MQ 安装的 bin 文件夹(例如 C:/mqseries/bin)。运行了批文件之后,应当看到消息 “All valid MQSC commands were processed ”。要打开 MQ Explorer 并检查已经创建的队列管理器和队列,请选择 Start -> Programs -> IBM MQSeries -> MQSeriesExplorer。图 1 显示出示例应用程序 QueueManager MQJMS.QManager 已经创建并正在运行。 图 1. WebSphere MQ 的 QueueManager 配置
请在应用程序屏幕左侧面板上点击 MQJMS.QManager 下的 Queues 文件夹。应当看到已经创建了一个队列 RequestResponseQueue ,如图 2 所示。 图 2. WebSphere MQ 的请求/响应队列配置
这就完成了队列的设置。 设置 JMS 和 JNDI 管理
在示例应用程序中,JNDI 的访问利用了可以从 JNDI 主页得到的基于文件的 FSContext 版本(请参阅 参考资料)。FSContext.jar 文件也包含在 WebSphere MQ 的 JMS 支持当中。请添加文件夹 /MQSeriesInstallable/MQSeries/Java/lib 和 /MQSeriesInstallable/MQSeries/Java/bin 到系统的 PATH 环境变量中。而且,请把 /MQSeriesInstallable/MQSeries/Java/lib 文件夹中的所有 jar 文件添加到系统的 CLASSPATH 环境变量中。还可以运行 C:/SpringSeriesPart4JMS/batch 文件夹中的 classpath.cmd 文件,它会设置必要的 path 和 CLASSPATH 变量。要做到这点,只需要修改 classpath.cmd 文件中的 MQ_JAVA_INSTALL_PATH ,把它指到 WebSphere MQ JMS 的安装目录。 接下来,修改 /MQSeriesInstallableDirectory/Java/bin 中的 JMSAdmin.config 配置文件,MQSeries JMS 管理程序用它指明应用程序要使用的上下文工厂和 JNDI 实现的地址。请取消以下行的注释: INITIAL_CONTEXT_FACTORY=com.sun.jndi.fscontext.RefFSContextFactory |
并注释掉其余两个 INITIAL_CONTEXT_FACTORY 变量。还要取消以下行的注释: PROVIDER_URL=file:/C:/JNDI-Directory |
并注释掉其余两个 PROVIDER_URL 变量。 可以在 C:/SpringSeriesPart4JMS/batch 文件夹中发现参考的示例配置文件。 为了保存 JNDI 对象,请在驱动器 C: 上创建名为 JNDI-Directory 的目录。切换到 /MQSeriesInstallableDirectory/Java/bin 目录并运行 JMSAdmin 批文件,应当看到 InitCtx 变量。 逐个输入以下内容: def qcf(MQ_JMS_MANAGER) qmgr(MQJMS.QManager)
按回车
def q(JMS_RequestResponseQueue) qmgr(MQJMS.QManager) queue(RequestResponseQueue)
按回车
|
现在已经把 WebSphere MQ 队列绑定到 JNDI 对象,作为应用程序客户可以通过 JNDI 查询对象。现在剩下的就是看代码的实际作用了!
| 回页首 |
|
运行示例 要运行示例,请从 spring sourceforge download 下载 Spring 框架和它的所有依赖文件并解压,例如解压到 c:/。会创建文件夹 C:/spring-framework-1.2-rc2(或最新版本)。 要运行 Spring 应用程序,请把本文的源代码解压到任意文件夹,例如 c:/。会创建文件夹 SpringSeriesPart4JMS。就像前面提到过的,还需要安装 Apache Ant 和它的 Spring 依赖 jar 文件。请把 Spring 库 —— 即 spring.jar(在 C:/spring-framework-1.2-rc2/dist 中)和 commons-logging.jar(在 C:/spring-framework-1.2-rc2/lib/jakarta-commons 中)拷贝到 SpringSeriesPart4JMS/lib 文件夹。还要把所有的 jar 库从 /MQSeriesInstallableDirectory/Java/lib 目录拷贝到 SpringSeriesPart4JMS/lib 文件夹。其中包含 MQseries 和 JMS 的相关库。现在就拥有了构建的依赖集。 接下来,打开命令提示符,切换到 SpringProject4 目录,并在命令提示符下输入以下命令: > ant -f build-jmssender.xml. |
这会构建并运行 SendMQSpringJMS 类,它会调用 JMSSender 类,发送消息到 WebSphere MQ RequestResponse 队列。SendMQSpringJMS 还会通过它的 ClassPathXmlApplicationContext 装入 spring 配置文件。一旦 bean 全部装载,就可以通过 Spring 的 ApplicationContext 的 getBean() 方法访问 JMSSender(请参阅清单 7)。 清单 7. 装入示例应用程序的 Spring 配置
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] { "spring-mqseries-jms.xml" }); JMSSender jmsSender = (JMSSender) appContext.getBean("jmsSender"); |
消息传递到队列上之后,请运行 JMS 接收方客户机以检索消息。请打开命令提示符,切换到目录 SpringProject4,并输入: > ant -f build-jmsreceiver.xml |
这会构建并运行 ReceiveMQSpringJMS 类,该类会调用 JMSReceiver 类,以从 WebSphere MQ 的 RequestResponse 队列接收文本消息。在控制台上会打印出以下消息: Message Received --> This is a sample message. |
结束语 在 Spring 系列的最后这篇文章中,您学习了 Spring JMS 框架的基础。我首先介绍了示例应用程序的核心组件 —— Spring JMS 框架和 IBM 的 WebSphere MQ 5.3,然后介绍了如何用 Spring JMS 模板向 WebSphere MQ 队列发送消息和从中接收消息。虽然这个示例非常简单,但是可以把这里介绍的步骤应用到更复杂的应用程序。 我希望介绍 Spring 框架核心模块的这一系列对您有所帮助。请参阅 参考资料 学习更多有关 Spring 框架和 Spring JMS 的内容。
| 回页首 |
|
下载 描述 | 名字 | 大小 | 下载方法 |
---|
Example code, Spring files, and build scripts | wa-spring4-SpringSeriesPart4JMS.zip | 17 KB | HTTP |
---|
参考资料 学习
- 您可以参阅本文在 developerWorks 全球站点上的 英文原文。
- “轻量级开发的成功秘诀,第 3 部分: Spring 露出水面”(Bruce Tate,developerWorks,2005 年 6 月):Bruce Tate 介绍了 Spring 作为轻量级容器的意义。
- “用 AXIS 编写 JMS 应用程序”(Naveen Balani,developerWorks,2003 年 2 月):开发同步 JMS SOAP 应用程序。
- Web 架构专区:数百篇涉及基于 Web 的解决方案的文章。
获得产品和技术
- Spring 主页:下载 Spring 框架。
- JMS 主页:下载 Java 消息服务。
- JNDI 主页:下载 JNDI 和 FSContext。
- WebSphere MQ:得到可信的、可靠的 JMS 提供者。
讨论
- 参与论坛讨论。
- developerWorks blogs:加入 developerWorks 社区。
关于作者 | | | Naveen Balani 把自己的大部分时间花在设计和开发基于 J2EE 的框架和产品上。他为 IBM developerWorks 撰写了各种不同的文章,涉及的主题包括:ESB、SOA、JMS、Web 服务架构、CICS、AXIS、DB2、XML Extender、WebSphere Studio、MQSeries、Java Wireless Devices and DB2 Everyplace for Palm、J2ME、MIDP、Java-Nokia、Visual Studio .Net,以及无线数据同步。可以通过他的电子邮件 naveenbalani@rediffmail.com 与他联系。 |
|