首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

用Spring JMS使异步讯息变得简单

2012-07-02 
用Spring JMS使异步消息变得简单table border0 cellspacing0 cellpadding0 width96% align

用Spring JMS使异步消息变得简单
   
<table border="0" cellspacing="0" cellpadding="0" width="96%" align="center"><tbody><tr><td>?</td></tr><tr><td height="24" align="center" valign="bottom">用spring jms使异步消息变得简单</td></tr><tr><td height="3">?</td></tr><tr><td>?</td></tr><tr><td src="http://17zouguo.iteye.com/files/uploadimg/20061024/1337380.jpg" border="0" alt="用Spring JMS使异步讯息变得简单" width="376" height="450">
表1:spring jms类
随后的部分,我将详细解释表1中的类(如jmstemplate, destinationresolver,和 messageconverter)。
#p#
jmstemplate
jmstemplate提供了几个helper方法来执行基本操作。开始使用jmstemplate前,有必要知道jms提供者支持哪种jms规范。jboss as 4.0.2 和 weblogic 8.1服务器支持jms1.0.2规范。weblogic 服务器 9.0包含jms1.1支持。jms1.1统一了ptp和pub/sub编程接口。有了这个改变,开发者可以创建一个事务会话,然后在同一个jms事务中,从queue(ptp)接受消息和发送一个消息到topic(pub/sub)。jms1.1向后兼容jms1.0,因此基于jms1.0编写的代码仍然能跟jms1.1工作。
jmstemplate提供各种方法来接收和发送消息。表2是方法列表。
<img src="http://17zouguo.iteye.com/files/uploadimg/20061024/1337381.jpg" border="0" alt="用Spring JMS使异步讯息变得简单" width="600">
表2:jms模板方法
使用jndi上下文存储和检索目的地。当配置spring应用上下文时,我们用jndiobjectfactorybean获得jms目的地引用。destinationresolver用来解析目的地名称到一个jms目的地,当应用有许多目的地时,那是很有帮助的。dynamicdestinationresolver(缺省destinationresolver实现)用于解析动态目的地。
messageconverter接口定义了java对象和jms消息之间转换的契约。使用转换器,应用代码可以专注于业务对象,不用操心它是如何代表jms消息的。simplemessageconverter(和simplemessageconverter102)是缺省messageconverter实现。它们用于将string、字节数组((byte[])、map、serializable对象分别转换成jms textmessage、jms bytesmessage,jms mapmessage,jms objectmessage。你可以编写messageconverter接口的定制实现并结合xml绑定框架如jaxb, castor, commons digester, xmlbeans, 或 xstream来转换xml文档到textmessage。
样本应用
我将用一个样本贷款应用处理系统(叫loanproc)来说明怎样在jms应用中使用spring。作为贷款处理的一部分,loanproc发送贷款详细资料(loan id, borrower name, borrower's ssn, loan expiration date, and loan amount)从aus系统请求信贷历史。为让例子简单一点,我们将基于两个参数:信用评分和贷款数量来获得信贷历史详细资料。让我们假定处理信用检查请求的业务规则如下:
1、如果贷款数量等于或小于$500,000,那么贷款人必须至少有一个“good”信用(例如,贷款人的信用评分在680到699之间);<br>2、如果贷款数量超过$500,000,那么贷款人必须至少要有一个“very good”信用,这意味他/她的信用评分超过700。
贷款应用use case
贷款请求处理use case由下列步骤组成:
1、用户在贷款申请web页面输入贷款详细资料并提交贷款申请;<br>2、然后程序发送贷款详细资料到aus系统取得信用历史详细资料。用发送请求到名叫creditrequestsendqueue的消息队列来完成。<br>3、aus系统从队列摘取贷款详细资料并用贷款参数来从数据库检索信用历史信息;<br>4、然后aus系统用找到的贷款人信用历史信息创建一个新的消息并发送到名叫creditrequestreceivequeue的消息队列;<br>5、最后loanproc从接收消息队列摘取响应消息并处理贷款申请,决定申请是被核准还是拒绝。
应用中,在同样的jboss mq server中配置了两个消息队列。use case用序列图1表示如下:
<img src="http://17zouguo.iteye.com/files/uploadimg/20061024/1337382.jpg" border="0" alt="用Spring JMS使异步讯息变得简单" width="600">
图1:贷款处理应用的序列图
技术
表3列出了例子应用中用到的一些技术和开源框架
<img src="http://17zouguo.iteye.com/files/uploadimg/20061024/1337383.jpg" border="0" alt="用Spring JMS使异步讯息变得简单">
表3:jms应用中用到的框架
#p#
使用hermes 的jms资源设置
为异步处理消息,首先,我们需要消息队列来发送和接收消息。我们在jboss中使用xml配置文件创建消息队列并且用jms控制台来浏览队列详细资料。清单1显示了xml配置文件jms配置片断。(这个片断可以被添加到%jboss_home%\server\all\deploy-hasingleton\jms目录下的jbossmq-destinations-service.xml文件中。)
清单1:jboss mq服务器中jms队列配置

<table border="1" cellspacing="0" cellpadding="2" width="400" align="center"><tbody><tr><td ? name="jboss.mq.destination:service=queue,name=creditrequestsendqueue">? ? <depends optional-attribute-name="destinationmanager">???????
jboss.mq:service=destinationmanager? ? </depends></mbean><!--? credit request receive queue? --><mbean code="org.jboss.mq.server.jmx.queue"???
name="jboss.mq.destination:service=queue,name=creditrequestreceivequeue">? <depends optional-attribute-name="destinationmanager">?????
jboss.mq:service=destinationmanager? </depends></mbean>  
</pre></td></tr></tbody></table>现在,让我们看看怎么使用一个叫做hermes的jms工具浏览消息队列。hermes是一个java swing应用,它能创建、管理和监控jms提供者中的jms destination。这样的jms提供者有jbossmq, webspheremq, activemq 和 arjuna。从website下载hermes并解压zip文件到一个本地目录(如c:\dev\tools\hermes)。一旦安装,双击hermes.bat (在bin目录)启动程序。
为在hermes中配置jbossmq服务器,参考hermes站点上的demo。它一步一步形象说明了jboss mq的配置。
当配置一个新的jndi初始上下文时,输入下面的配置信息。

<table border="1" cellspacing="0" cellpadding="2" width="400" align="center"><tbody><tr><td src="http://17zouguo.iteye.com/files/uploadimg/20061024/1337384.jpg" border="0" alt="用Spring JMS使异步讯息变得简单">
图2:hermes中所有destinations的截屏
图3是消息发送者发送一些消息到creditrequestsendqueue后,hermes jms控制台显示的消息队列详细资料。你能看到这里队列中有5个消息并且控制台显示了消息的详细信息如message id、message destination、time stamp、和实际的消息。
<img src="http://17zouguo.iteye.com/files/uploadimg/20061024/1337385.jpg" border="0" alt="用Spring JMS使异步讯息变得简单">
图3:hermes中队列详细资料截屏
使用spring jms,异步消息变得简单
用在样本应用中的这些消息队列名和其它jms以及jndi参数如下表4所示。
<img src="http://17zouguo.iteye.com/files/uploadimg/20061024/1337386.jpg" border="0" alt="用Spring JMS使异步讯息变得简单">
表4:spring jms配置参数
#p#
spring配置
已经有了运行样本应用所需的jms destinations,现在该是进入用xml spring配置文件(叫做spring-jms.xml)装配jms组件的细节的时候了。用ioc设计模式中的setter依赖注入原理装入这些组件。让我们仔细看看组件,为每一个jms组件显示了一个xml配置片断。
jndi上下文是获取jms资源的入口,所以我们首先配置一个jndi模板。清单2显示了一名为jnditemplate的spring bean,它具有取得jndi初始上下文必须的常用参数。
清单2:jndi上下文模板

<table border="1" cellspacing="0" cellpadding="2" width="400" align="center"><tbody><tr><td cellspacing="0" cellpadding="2" width="400" align="center"><tbody><tr><td cellspacing="0" cellpadding="2" width="400" align="center"><tbody><tr><td cellspacing="0" cellpadding="2" width="400" align="center"><tbody><tr><td cellspacing="0" cellpadding="2" width="400" align="center"><tbody><tr><td cellspacing="0" cellpadding="2" width="400" align="center"><tbody><tr><td cellspacing="0" cellpadding="2" width="400" align="center"><tbody><tr><td cellspacing="0" cellpadding="2" width="400" align="center"><tbody><tr><td + 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 connction.?? */??? 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></td></tr></tbody></table>现在,让我们看看用spring实现的消息发送者。清单10显示了messagesenderspringjms类中send方法代码。
清单10:用spring api的jms实现

<table border="1" cellspacing="0" cellpadding="2" width="400" align="center"><tbody><tr><td class="code"><pre>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></td></tr></tbody></table>如你所见,所有与管理jms资源相关的资源步骤都由spring容器用配置文件处理。我们仅需要获取jmssender引用并且调用它上面的sendmessage即可。
结论
本文中,我们看到spring框架如何简化了使用jms api的异步消息应用开发的工作。spring移走了所有jms消息处理必须的样板代码,如获取连接工厂,从java代码创建队列和会话对象并在运行时用配置文件装配它们。由于这个强大的ioc原理,我们可以不必修改java代码便可动态交换jms资源对象。
因为异步消息是构成soa框架整体所需的一部分,spring非常适合放入soa工具集。同样,jms管理工具如hermes使得创建,管理和控制jms资源变得简单,尤其对系统管理员。
<p align="right">(责任编辑 火凤凰 sunsj@51cto.com? tel:(010)68476636-8007)</td></tr><tr><td class="d_font4">?</td></tr></tbody></table> 

热点排行