﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-clant-文章分类-JMS</title><link>http://www.blogjava.net/clant/category/17975.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 16:21:57 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 16:21:57 GMT</pubDate><ttl>60</ttl><item><title>JMS消息中间件开源实现</title><link>http://www.blogjava.net/clant/articles/85156.html</link><dc:creator>BPM </dc:creator><author>BPM </author><pubDate>Sun, 03 Dec 2006 02:38:00 GMT</pubDate><guid>http://www.blogjava.net/clant/articles/85156.html</guid><wfw:comment>http://www.blogjava.net/clant/comments/85156.html</wfw:comment><comments>http://www.blogjava.net/clant/articles/85156.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/clant/comments/commentRss/85156.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/clant/services/trackbacks/85156.html</trackback:ping><description><![CDATA[
		<a href="http://www.open-open.com/53.htm">http://www.open-open.com/53.htm</a>
<img src ="http://www.blogjava.net/clant/aggbug/85156.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/clant/" target="_blank">BPM </a> 2006-12-03 10:38 <a href="http://www.blogjava.net/clant/articles/85156.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JMS框架开源实现</title><link>http://www.blogjava.net/clant/articles/85158.html</link><dc:creator>BPM </dc:creator><author>BPM </author><pubDate>Sun, 03 Dec 2006 02:38:00 GMT</pubDate><guid>http://www.blogjava.net/clant/articles/85158.html</guid><wfw:comment>http://www.blogjava.net/clant/comments/85158.html</wfw:comment><comments>http://www.blogjava.net/clant/articles/85158.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/clant/comments/commentRss/85158.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/clant/services/trackbacks/85158.html</trackback:ping><description><![CDATA[
		<a href="http://www.open-open.com/37.htm">http://www.open-open.com/37.htm</a>
<img src ="http://www.blogjava.net/clant/aggbug/85158.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/clant/" target="_blank">BPM </a> 2006-12-03 10:38 <a href="http://www.blogjava.net/clant/articles/85158.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Spring JMS轻松实现异步消息传递</title><link>http://www.blogjava.net/clant/articles/85151.html</link><dc:creator>BPM </dc:creator><author>BPM </author><pubDate>Sun, 03 Dec 2006 02:11:00 GMT</pubDate><guid>http://www.blogjava.net/clant/articles/85151.html</guid><wfw:comment>http://www.blogjava.net/clant/comments/85151.html</wfw:comment><comments>http://www.blogjava.net/clant/articles/85151.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/clant/comments/commentRss/85151.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/clant/services/trackbacks/85151.html</trackback:ping><description><![CDATA[      异步进程通信是面向服务架构(SOA)一个重要的组成部分，因为企业里很多系统通信，特别是与外部组织间的通信，实质上都是异步的。<a href="http://java.sun.com/products/jms/" target="_blank">Java消息服务</a>(JMS)是用于编写使用异步消息传递的JEE应用程序的API。传统的使用JMS API进行消息传递的实现包括多个步骤，例如JNDI查询队列连接工厂和Queue资源，在实际发送和接收消息前创建一个JMS会话。 
<p>　　 <a href="http://www.springframework.org/" target="_blank"><font color="#800080">Spring框架</font></a>则简化了使用JEE组件(包括JMS)的任务。它提供的模板机制隐藏了典型的JMS实现的细节，这样开发人员可以集中精力放在处理消息的实际工作中，而不用担心如何去创建，访问或清除JMS资源。</p><p>　　 本文将对Spring JMS API作一个概述，并通过一个运行在JBoss MQ服务器上的web例程来介绍如何使用Spring JMS API来异步处理（发送和接收）消息。我将通过传统JMS实现和Spring JMS实现两者间的比较，来展示使用Spring JMS处理消息是如何的简单和灵活。</p><h3>异步消息传递和面向服务架构</h3><p>　　在现实中，大多数web请求都是同步处理的。例如，当用户要登入一个网站，首先输入用户名和密码，然后服务器验证登录合法性。如果验证成功，程序将允许该用户进入网站。这里，登录请求在从客户端接收以后被即时处理了。信用卡验证是另一个同步处理的例子；只有服务器证实输入的信用卡号是有效的，同时客户在帐户上有足够的存款，客户才被允许继续操作。但是让我们思考一下在顺序处理系统上的支付结算步骤。一旦系统证实该用户信用卡的信息是准确的，并且在帐户上有足够的资金，就不必等到所有的支付细节落实、转账完成。支付结算可以异步方式进行，这样客户可以继续进行核查操作。</p><p>　　 需要比典型同步请求耗费更长时间的请求，可以使用异步处理。另一个异步处理的例子是，在本地贷款处理程序中，提交至自动承销系统（AUS）的信用请求处理过程。当借方提交贷款申请后，抵押公司会向AUS发送请求，以获取信用历史记录。由于这个请求要求得到全面而又详细的信用报告，包括借方现今和过去的帐户，最近的付款和其他财务资料，服务器需要耗费较长的时间（几小时或着有时甚至是几天）来对这些请求作出响应。客户端程序（应用）要与服务器连接并耗费如此长的时间来等待结果，这是毫无意义的。因此通信应该是异步发生的；也就是，一旦请求被提交，它就被放置在队列中，同时客户端与服务器断开连接。然后AUS服务从指定的队列中选出请求进行处理，并将处理得到的消息放置在另一个消息队列里。最后，客户端程序从这个队列中选出处理结果，紧接着处理这个信用历史数据。</p><h3>JMS</h3><p>　　 如果您使用过JMS代码，您会发现它与JDBC或JCA很像。它所包含的样本代码创建或JMS资源对象回溯，使得每一次您需要写一个新类来发送和接收消息时，都具有更好的代码密集性和重复性。以下序列显示了传统JMS实现所包括的步骤：</p><ol type="1"><li>创建JNDI初始上下文（context）。 
</li><li>从JNDI上下文获取一个队列连接工厂。 
</li><li>从队列连接工厂中获取一个Quene。 
</li><li>创建一个Session对象。 
</li><li>创建一个发送者（sender）或接收者（receiver）对象。 
</li><li>使用步骤5创建的发送者或接收者对象发送或接收消息。 
</li><li>处理完消息后，关闭所有JMS资源。 </li></ol>您可以看到，步骤6是处理消息的唯一地方。其他步骤都只是管理与实际业务要求无关的JMS资源，但是开发人员必须编写并维护这些额外步骤的代码。 
<p> </p><h3>Spring JMS</h3><p>　　 Spring框架提供了一个模板机制来隐藏Java APIs的细节。JEE开发人员可以使用JDBCTemplate和JNDITemplate类来分别访问后台数据库和JEE资源（数据源，连接池）。JMS也不例外。Spring提供JMSTemplate类，因此开发人员不用为一个JMS实现去编写样本代码。接下来是在开发JMS应用程序时Spring所具有一些的优势。</p><ol type="1"><li>提供JMS抽象API，简化了访问目标（队列或主题）和向指定目标发布消息时JMS的使用。 
</li><li>JEE开发人员不需要关心JMS不同版本（例如JMS 1.0.2与JMS 1.1）之间的差异。 
</li><li>开发人员不必专门处理JMS异常，因为Spring为所有JMS异常提供了一个未经检查的异常，并在JMS代码中重新抛出。 </li></ol>一旦您在JMS应用程序中开始使用Spring，您将会欣赏到它在处理异步消息传递上的简便。Spring JMS框架提供多种Java类，可以轻松实现JMS应用。表1列出了这些类的一部分。 
<p> </p><p>　　 表1. Spring JMS类</p><table class="tabel-general" cellspacing="0" cellpadding="0" width="100%"><tbody><tr><th class="left">类名</th><th class="center">包</th><th class="right">功能</th></tr><tr><td class="left">JmsException</td><td class="center">org.springframework.jms</td><td class="right">只要发生一个JMS异常，Spring框架就会抛出异常，这个类是这些所抛出的异常的基（抽象）类。</td></tr><tr><td class="left">JmsTemplate, JmsTemplate102</td><td class="center">org.springframework.jms.core</td><td class="right">这些是辅助类，用于简化JMS的使用，处理JMS资源（如连接工厂，目标和发送者/接收者对象）的创建和释放。JmsTemplate102是JmsTemplate的子类，使用JMS1.0.2规范</td></tr><tr><td class="left">MessageCreator</td><td class="center">org.springframework.jms.core</td><td class="right">这是JmsTemplate类使用的回叫接口，它为指定的会话创建JMS消息。</td></tr><tr><td class="left">MessageConverter</td><td class="center">org.springframework.jms.support.converter</td><td class="right">这个接口充当一个抽象，用来在Java对象与JMS消息之间进行转换。</td></tr><tr><td class="left">DestinationResolver</td><td class="center">org.springframework.jms.support.destination</td><td class="right">这是JmsTemplate用来解析目标名的接口。该接口的默认实现是DynamicDestinationResolver和JndiDestinationResolve</td></tr></tbody></table><p>　　在接下来的部分，我将详细解释表1所列的一部分类（例如JmsTemplate，DestinationResolver和MessageConverter）。</p><h3>JMSTemplate</h3><p>　　JmsTemplate提供了几种辅助方法，用来执行一些基本操作。要开始使用JmsTemplate前，您需要知道JMS供应商支持哪个JMS规范，<a href="http://www.jboss.com/products/jbossas" target="_blank">JBoss AS 4.0.2</a>和<a href="http://www.bea.com/" target="_blank">WebLogic 8.1</a>服务器支持JMS 1.0.2规范。WebLogic Server 9.0包括了对<a href="http://java.sun.com/products/jms/" target="_blank">JMS 1.1</a>规范的<a href="http://dev2dev.bea.com/pub/a/2005/09/weblogic9_jms.html" target="_blank">支持</a>。JMS 1.1统一了点对点（PTP）和发布/订阅（Pub/Sub）域的编程接口。这种改变的结果就是，开发人员可以创建一个事务会话，然后在这同一个JMS会话里，可以从一个Queue(PTP)中接收消息，同时发送另一个消息到一个Topic(Pub/Sub)。JMS 1.1向后兼容JMS 1.0，应此根据JMS 1.0编写的代码仍可以适用于JMS 1.1。</p><p>　　 JmsTemplate提供多种发送和接收消息的方法。表2列出了这些方法的一部分。</p><p>　　 表2. JMS template方法</p><table class="tabel-general" cellspacing="0" cellpadding="0" width="100%"><tbody><tr><th class="left">方法名称</th><th class="right">功能</th></tr><tr><td class="left">send</td><td class="right">发送消息至默认或指定的目标。JmsTemplate包含send方法，它通过javax.jms.Destination或JNDI查询来指定目标。</td></tr><tr><td class="left">receive</td><td class="right">从默认或指定的目标接收消息，但只会在指定的时间后传递消息。我们可以通过receiveTimeout属性指定超时时间。</td></tr><tr><td class="left">convertAndSend</td><td class="right">这个方法委托MessageConverter<a href="http://www.onjava.com/pub/a/onjava/2006/02/22/asynchronous-messaging-with-spring-jms.html?page=2#" target="_blank">接口</a>实例处理转换过程，然后发送消息至指定的目标。</td></tr><tr><td class="left">receiveAndConvert</td><td class="right">从默认或指定的目标接收消息。并将消息转换为Java对象。</td></tr></tbody></table><p>　　目标可以通过JNDI上下文保存和获取。当配置Spring程序上下文（application context）时，我们可以用JndiObjectFactoryBean类取得对JMS的引用。DestinationResolver接口是用来把目标名称解析成JMS目标，当应用程序存在大量目标时，这是非常有用的。DynamicDestinationResolver(DestinationResolver的默认实现)是用来解析动态目标的。</p><p>　　 MessageConverter接口定义了将<a href="http://www.onjava.com/pub/a/onjava/2006/02/22/asynchronous-messaging-with-spring-jms.html?page=2" target="_blank">Java对象</a>转换为JMS消息的约定。通过这个转换器，应用程序代码可以集中于处理事务对象，而不用为对象如何表示为JMS消息这样的内部细节所困饶。SimpleMessageConverter(和SimpleMessageConverter102)是MessageConverter的默认实现。可使用它们分别将String转换为JMS TextMessage，字节数组(byte[])转换为JMS BytesMessage，Map转换为JMS MapMessage，和Serializable对象转换为JMS ObjectMessage。您也可以编写自定义的MessageConverter实例，通过XML绑定框架（例如<a href="http://java.sun.com/webservices/jaxb/index.jsp" target="_blank">JAXB</a>， <a href="http://www.castor.org/" target="_blank">Castor</a>，<a href="http://jakarta.apache.org/commons/digester/" target="_blank">Commons Digester</a>，<a href="http://xmlbeans.apache.org/" target="_blank">XMLBeans</a>或<a href="http://xstream.codehaus.org/" target="_blank">XStream</a>），来实现XML文档到TextMessage对象的转换。</p><h3>示例程序</h3><p>　　我将用一个贷款申请处理系统（命名为LoanProc）示例来演示如何在JMS应用程序中使用Spring。作为贷款申请的一部分，LoanProc通过发送贷款详情（贷款ID，借方名字，借方的SSN，贷款期限和贷款数额），从AUS系统获得信用历史详情。为了简便起见，我们基于两个基本参数来表示信用历史详情：信用分数（又名FICO得分）和贷款数额。让我们假设处理信用检查请求是按以下业务规则进行的：</p><ol type="1"><li>如果贷款数额等于或低于,000，借方必须至少有一个"好"的信用（也就是，借方的FICO得分在680到699之间）。 
</li><li>如果贷款数额高于,000，借方必须至少有"很好"的信用，意味着借方的信用得分要高于700。 </li></ol><h3>贷款申请使用案例</h3><p>　　信用请求处理使用案例包括以下几个步骤：</p><ol type="1"><li>用户在贷款申请页面输入贷款详情并提交贷款申请。 
</li><li>发送请求到一个名为CreditRequestSendQueue的消息队列。然后程序发送贷款详情到AUS系统，获取信用历史详情。 
</li><li>AUS系统从队列中挑出贷款详情，并使用贷款参数从它的数据库中获取信用历史信息。 
</li><li>然后AUS将找到的借方的信用历史信息创建一个新的消息，发送到一个新的名为CreditRequestReceiveQueue的消息队列。 
</li><li>最后，LoanProc从接收队列中选出响应消息，处理贷款申请来决定是否批准或否决申请。 </li></ol><p>　　在这个例程中，两个消息队列都配置在同一个JBoss MQ server上。使用案例用图1的序列图（SequenceDiagram）表示</p><p align="center"><a href="http://www.onjava.com/onjava/2006/02/22/graphics/LoanAppSpringJMSSequenceDiagram_lg.jpg" target="_blank"><img height="169" alt="序列图" src="http://dev2dev.bea.com.cn/images/image060511001.gif" width="300" border="0" /></a><br /><br />图1.贷款处理程序的序列图 (单击截图来查看完整视图)</p><p>　　 下面的表3显示了在例程中我所使用的不同技术和<u><a href="http://www.onjava.com/pub/a/onjava/2006/02/22/asynchronous-messaging-with-spring-jms.html?page=3" target="_blank">开源</a></u>框架，并按应用逻辑层排列。</p><p>　　 表3. 在JMS应用程序中使用的框架</p><table class="tabel-general" cellspacing="0" cellpadding="0" width="100%"><tbody><tr><th class="left">逻辑层</th><th class="right">技术/框架</th></tr><tr><td class="left">MVC</td><td class="right">Spring MVC</td></tr><tr><td class="left">Service</td><td class="right">Spring Framework (version 2.1)</td></tr><tr><td class="left">JMS API</td><td class="right">Spring JMS</td></tr><tr><td class="left">JMS Provider</td><td class="right"><a href="http://www.onjava.com/pub/a/onjava/2006/02/22/asynchronous-messaging-with-spring-jms.html?page=3#" target="_blank">JBoss</a> MQ (version 4.0.2)</td></tr><tr><td class="left">JMS Console</td><td class="right">Hermes</td></tr><tr><td class="left">IDE</td><td class="right">Eclipse 3.1</td></tr></tbody></table><h3>使用Hermes设置JMS资源</h3><p>　　为了异步处理消息，首先我们需要消息队列发送和接收消息。我们可以用Jboss里的配置<a href="http://www.onjava.com/pub/a/onjava/2006/02/22/asynchronous-messaging-with-spring-jms.html?page=3#" target="_blank">XML文件</a>创建一个新的消息队列，然后使用JMS控制台浏览队列的详细情况。清单1显示了配置JMS的XML配置代码片断（这个应该加入到jbossmq-destinations-service.xml文件，位于%JBOSS_HOME%server lldeploy-hasingletonjm文件夹下。）</p><p>　　 清单1.JBoss MQ Server上JMS队列的配置</p><pre class="code">&lt;!--  Credit Request Send Queue  --&gt;
&lt;mbean code="org.jboss.mq.server.jmx.Queue"
  name="jboss.mq.destination:service=Queue,name=CreditRequestSendQueue"&gt;
  &lt;depends optional-attribute-name="DestinationManager"&gt;
 jboss.mq:service=DestinationManager
  &lt;/depends&gt;
&lt;/mbean&gt;

&lt;!--  Credit Request Receive Queue  --&gt;
&lt;mbean code="org.jboss.mq.server.jmx.Queue"
  name="jboss.mq.destination:service=Queue,name=CreditRequestReceiveQueue"&gt;
  &lt;depends optional-attribute-name="DestinationManager"&gt;
 jboss.mq:service=DestinationManager
  &lt;/depends&gt;
&lt;/mbean&gt;
</pre><p>　　现在，让我们看看如何使用一个名为Hermes的JMS工具来浏览消息队列。<a href="http://www.hermesjms.com/" target="_blank">Hermes</a>是一个Java Swing应用程序，它可以创建、管理和监视JMS提供商（例如<a href="http://www.jboss.com/products/jbossas" target="_blank">JBossMQ</a>，<a href="http://www-306.ibm.com/software/integration/wmq/" target="_blank">WebSphereMQ</a>，<a href="http://www.activemq.org/" target="_blank">ActiveMQ</a>和<a href="http://www.arjuna.com/products/arjunams/" target="_blank">Arjuna</a>服务器）里的JMS目标。从它的<a href="http://sourceforge.net/projects/hermesjms" target="_blank">网站</a>上下载Hermes，解压缩.zip文件到本地目录（例如，c:dev oolshermes）。一旦安装完成，双击文件hermes.bat（位于bin文件夹下）启动程序。</p><p>　　 要在Hermes里配置JBossMQ服务器，请参考Hermes网站上的这个<a href="http://www.hermesjms.com/demos/jboss_config.html" target="_blank">演示</a>。它有着出色的step-by-step可视化指示来配置JBoss MQ。当配置一个新的JNDI初始上下文时，请输入下面的信息。</p><ul type="disc"><li>providerURL = jnp://localhost:1099 
</li><li>initialContextFactory = org.jnp.interfaces.NamingContextFactory 
</li><li>urlPkgPrefixes = org.jnp.interfaces:org.jboss.naming 
</li><li>securityCredentials = admin 
</li><li>securityPrincipal = admin </li></ul><p>　　当您创建新的目标时，请输入queue/CreditRequestSendQueue和queue/CreditRequestReceiveQueue。图2显示了JMS控制台的主窗口，其中有为JMS例程创建的新的消息队列。</p><p align="center"><a href="http://www.onjava.com/onjava/2006/02/22/graphics/HermesJMSDestinations_lg.jpg" target="_blank"><img height="159" alt="Hermes中所有目标的截图" src="http://dev2dev.bea.com.cn/images/image060511003.jpg" width="312" border="0" /></a><br /><br />图 2. Hermes中所有目标的截图.（单击截图来查看完整视图）</p><p>　　 下面的图3显示了在从消息发送者类发送消息到CreditRequestSendQueue后，Hermes JMS控制台及消息队列的截图。您可以看见有5个消息在队列中，控制台显示了消息详情，例如消息ID，消息目标，时间戳和实际的消息内容。</p><p align="center"><a href="http://www.onjava.com/onjava/2006/02/22/graphics/HermesJMSQueueDetails_lg.jpg" target="_blank"><img height="159" alt="Hermes中所有队列的截图" src="http://dev2dev.bea.com.cn/images/image060511005.jpg" width="312" border="0" /></a><br /><br />图 3. Hermes中所有队列的截图.（单击截图来查看完整视图）</p><p>　　 在例程中使用的队列名称和其他JMS和JNDI参数见表 4。</p><p>　　 表4. Spring JMS配置参数</p><table class="tabel-general" cellspacing="0" cellpadding="0" width="100%"><tbody><tr><th class="left">参数名称</th><th class="right">参数值</th></tr><tr><td class="left">Initial Context Factory</td><td class="right">org.jnp.interfaces.NamingContextFactory</td></tr><tr><td class="left">Provider URL</td><td class="right">localhost:8080</td></tr><tr><td class="left">Initial Context Factory URL Packages</td><td class="right">org.jnp.interfaces:org.jboss.naming</td></tr><tr><td class="left">Queue Connection Factory</td><td class="right">UIL2ConnectionFactory</td></tr><tr><td class="left">Queue Name</td><td class="right">queue/CreditRequestSendQueue, queue/CreditRequestReceiveQueue</td></tr></tbody></table><h3>Spring配置</h3><p>　　既然我们已经有了运行例程所需要的JMS目标，现在该了解用<a href="http://www.onjava.com/pub/a/onjava/2006/02/22/asynchronous-messaging-with-spring-jms.html?page=4#" target="_blank">XML</a> Spring配置文件（名为spring-jms.xml）来组配JMS组件的具体细节了。这些组件是根据Inversion of Controller (IOC)<a href="http://www.onjava.com/pub/a/onjava/2006/02/22/asynchronous-messaging-with-spring-jms.html?page=4#" target="_blank">设计模式</a>里的设置方式注入原则（setter injection principle），用JMS对象实例类组配的。让我们详细查看这些组件，并为每一个JMS组件演示一段XML配置代码。</p><p>　　 JNDI上下文是取得JMS资源的起始位置，因此首先我们要配置JNDI模板。清单2显示了名为jndiTemplate的Spring bean，其中列有JNDI初始上下文所必需的常用参数。</p><p>　　 清单2. JNDI上下文模板</p><pre class="code">&lt;bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate"&gt;
    &lt;property name="environment"&gt;
        &lt;props&gt;
            &lt;prop key="java.naming.factory.initial"&gt;
                org.jnp.interfaces.NamingContextFactory
            &lt;/prop&gt;
            &lt;prop key="java.naming.provider.url"&gt;
                localhost
            &lt;/prop&gt;
            &lt;prop key="java.naming.factory.url.pkgs"&gt;
                org.jnp.interfaces:org.jboss.naming
            &lt;/prop&gt;
        &lt;/props&gt;
    &lt;/property&gt;
&lt;/bean&gt;
</pre><p>　　接着，我们配置队列连接工厂。清单3显示了队列连接工厂的配置。</p><p>　　 清单3. JMS队列连接工厂配置</p><pre class="code">&lt;bean id="jmsQueueConnectionFactory"
      class="org.springframework.jndi.JndiObjectFactoryBean"&gt;
    &lt;property name="jndiTemplate"&gt;
        &lt;ref bean="jndiTemplate"/&gt;
    &lt;/property&gt;
    &lt;property name="jndiName"&gt;
        &lt;value&gt;UIL2ConnectionFactory&lt;/value&gt;
    &lt;/property&gt;
&lt;/bean&gt;
</pre><p>　　我们定义2个JMS目标来发送和接收消息。详情见清单4和5。</p><p>　　 清单4. 发送队列配置</p><pre class="code">&lt;bean id="sendDestination"
    class="org.springframework.jndi.JndiObjectFactoryBean"&gt;
    &lt;property name="jndiTemplate"&gt;
        &lt;ref bean="jndiTemplate"/&gt;
    &lt;/property&gt;
    &lt;property name="jndiName"&gt;
        &lt;value&gt;queue/CreditRequestSendQueue&lt;/value&gt;
    &lt;/property&gt;
&lt;/bean&gt;
</pre><p>　　清单5. 接收队列配置</p><pre class="code">&lt;bean id="receiveDestination"
    class="org.springframework.jndi.JndiObjectFactoryBean"&gt;
    &lt;property name="jndiTemplate"&gt;
        &lt;ref bean="jndiTemplate"/&gt;
    &lt;/property&gt;
    &lt;property name="jndiName"&gt;
        &lt;value&gt;queue/CreditReqeustReceiveQueue&lt;/value&gt;
    &lt;/property&gt;
&lt;/bean&gt;
</pre><p>　　然后我们再来配置JmsTemplate组件。在例程中我们使用JmsTemplate102。同时使用defaultDestination属性来指定JMS目标。</p><p>　　 清单6. JMS模板配置</p><pre class="code">&lt;bean id="jmsTemplate" 
      class="org.springframework.jms.core.JmsTemplate102"&gt;
    &lt;property name="connectionFactory"&gt;
        &lt;ref bean="jmsQueueConnectionFactory"/&gt;
    &lt;/property&gt;
    &lt;property name="defaultDestination"&gt;
        &lt;ref bean="destination"/&gt;
    &lt;/property&gt;
    &lt;property name="receiveTimeout"&gt;
        &lt;value&gt;30000&lt;/value&gt;
    &lt;/property&gt;
&lt;/bean&gt;
</pre><p>　　最后我们配置发送者和接收者组件。清单7和8分别是Sender 和 Receiver对象的配置。</p><p>　　 清单7. JMS Sender配置</p><pre class="code">&lt;bean id="jmsSender" class="springexample.client.JMSSender"&gt;
    &lt;property name="jmsTemplate"&gt;
        &lt;ref bean="jmsTemplate"/&gt;
    &lt;/property&gt;
&lt;/bean&gt;
</pre><p>　　清单8. JMS Receiver配置</p><pre class="code">&lt;bean id="jmsReceiver" class="springexample.client.JMSReceiver"&gt;
    &lt;property name="jmsTemplate"&gt;
        &lt;ref bean="jmsTemplate"/&gt;
    &lt;/property&gt;
&lt;/bean&gt;
</pre><h3>测试及监视</h3><p>　　我写了一个测试类，命名为LoanApplicationControllerTest，用来测试LoanProc程序。我们可以使用这个类来设定贷款参数以及调用信用请求服务类。</p><p>　　 让我们看一下不使用Spring JMS API而使用传统JMS开发途径的消息发送者实例。清单9显示了MessageSenderJMS类里的sendMessage方法，其中包含了使用JMS API处理消息的所有必需步骤。</p><p>　　 清单9. 传统JMS实例</p><pre class="code">public void sendMessage() {

    queueName = "queue/CreditRequestSendQueue";
    System.out.println("Queue name is " + queueName);

    /*
     * Create JNDI Initial Context
     */
    try {
        Hashtable env = new Hashtable();
        env.put("java.naming.factory.initial",
            "org.jnp.interfaces.NamingContextFactory");
        env.put("java.naming.provider.url","localhost");
        env.put("java.naming.factory.url.pkgs",
            "org.jnp.interfaces:org.jboss.naming");

        jndiContext = new InitialContext(env);
    } catch (NamingException e) {
        System.out.println("Could not create JNDI API " +
            "context: " + e.toString());
    }

    /*
     * Get queue connection factory and queue objects from JNDI context.
     */
    try {
        queueConnectionFactory = (QueueConnectionFactory)
        jndiContext.lookup("UIL2ConnectionFactory");

        queue = (Queue) jndiContext.lookup(queueName);
    } catch (NamingException e) {
        System.out.println("JNDI API lookup failed: " +
            e.toString());
    }

    /*
     * Create connection, session, sender objects.
     * Send the message.
     * Cleanup JMS connection.
     */
    try {
        queueConnection =
            queueConnectionFactory.createQueueConnection();
        queueSession = queueConnection.createQueueSession(false,
                Session.AUTO_ACKNOWLEDGE);
        queueSender = queueSession.createSender(queue);
        message = queueSession.createTextMessage();
        message.setText("This is a sample JMS message.");
        System.out.println("Sending message: " + message.getText());
        queueSender.send(message);

    } catch (JMSException e) {
        System.out.println("Exception occurred: " + e.toString());
    } finally {
        if (queueConnection != null) {
            try {
                queueConnection.close();
            } catch (JMSException e) {}
        }
    }
}
</pre><p>　　现在，我们来看看使用了Spring的消息发送者实例。清单10显示了MessageSenderSpringJMS类中send方法的代码。</p><p>　　 清单10. 使用Spring API的JMS实例</p><pre class="code">public void send() {
    try {
        ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] {
                "spring-jms.xml"});

        System.out.println("Classpath loaded");

        JMSSender jmsSender = (JMSSender)appContext.getBean("jmsSender");

        jmsSender.sendMesage();

        System.out.println("Message sent using Spring JMS.");
    } catch(Exception e) {
        e.printStackTrace();
    }
}
</pre><p>　　如您所见，通过使用配置文件，所有与管理JMS资源有关的步骤都将交由Spring容器处理。我们只需引用一个JMSSender对象，然后调用对象里的sendMessage方法。</p><h3>结束语</h3><p>　　在本文中，我们看到Spring框架是如何使用JMS API简化异步消息传递。Spring去掉了所有使用JMS处理消息所必需的样本代码（例如得到一个队列连接工厂，从Java代码里创建队列和会话对象，在运行时使用配置文件对它们进行组配）。我们可以动态的交换JMS资源对象，而不必修改任何Java代码，这要感谢Inversion of Control (IOC) 原则的力量。</p><p>　　既然异步消息传递是SOA框架的整体构成部分，Spring很适合纳入到SOA工具集。此外，JMS管理工具（如Hermes）使得创建、管理和监督JMS资源变得容易，特别是对于系统管理员来说。</p><h3>参考资料</h3><ul type="disc"><li>本文配套的<a href="http://www.onjava.com/onjava/2006/02/22/examples/sample-code.zip" target="_blank">示例代码</a></li><li><a href="http://static.springframework.org/spring/docs/1.2.x/reference/index.html" target="_blank">Spring JMS documentation</a></li><li>"<a href="http://www-128.ibm.com/developerworks/web/library/wa-spring4/" target="_blank">1-2-3 Messaging with Spring JMS</a>" 
</li><li><a href="http://wiki.jboss.org/wiki/Wiki.jsp?page=JBossMQ" target="_blank">JBoss MQ wiki</a></li></ul><p><strong>原文出处:</strong><a href="http://www.onjava.com/pub/a/onjava/2006/02/22/asynchronous-messaging-with-spring-jms.html" target="_blank">http://www.onjava.com/pub/a/onjava/2006/02/22/asynchronous-messaging-with-spring-jms.html</a></p><img src ="http://www.blogjava.net/clant/aggbug/85151.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/clant/" target="_blank">BPM </a> 2006-12-03 10:11 <a href="http://www.blogjava.net/clant/articles/85151.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>