mule in action翻译16 : 3.4 使用JMS传输
3.4 使用JMS传输
HTTP的流行使web service成为一种“诱人”的应用集成方式。但HTTP并不是为应用集成而生的,它不能保证传输的时间、可靠性及安全性。WS-* 规范试图在这方面做出突破,但比较复杂,且只是限制在SOAP内使用。幸运的是JMS协议是在防火墙范围内的一个“令人注目”的选择。来看mule对JMS的支持。
如果你用的java技术而且网络是完全受控的,那么使用JMS是个很好的选择,它是异步的可靠的、安全的而且速度非常快。它不限制运载的数据的类型,甚至你可以通过它在不同的JVM之间传输序列化的java对象。
本节我们将探索MULE对JMS的支持,先看怎么从队列或话题收发消息。而后学习如何使用过滤器筛选接受和发送的JMS消息。最后看在endpoint如何使用JMS消息执行异步操作--一般是异步的方式。
JMS传输可用来与队列或话题间进行JMS消息发送和接收--使用1.0.2b 或 1.1 版的JMS规范。Mule没有实现JMS服务器,所以你要联合使用一个如ActiveMQ或HornetQ的JMS实现来使用JMS传输。
有时配置JMS代理还真是有点不好办。为了能很好的与JMS实现协同工作,
mule提供了大量的关于JMS 连接器和endpoint的配置选项。
表3.3 列出了其中一些:
3.4.1 使用JMS outbound endpoint 发送JMS消息
现在使用JMS outbound endpoint向队列发送JMS消息。回顾列表3.3 中配置的接收Arnor Accounting 处理完支出报表的通知的流。这个流接收通知,并保存到一个文件。一种更真实的情况是,把消息发送到一个JMS topic ,其它的相关系统来订阅这个topic,这样一旦支出报表处理完毕相关系统就会接到通知。
如下列表展示(见图 3.11)
Listing 3.14 Publish expense reports to a JMS topic
<注释1 配置 activemq-connector> <jms:activemq-connector name="jmsConnector" specification="1.1" brokerURL="${jms.url}"/> <!--配置HTTP inbound endpoint--> <flow name="dispatchExpenseReports"> <http:inbound-endpoint exchange-pattern="one-way" host="${http.host}" path="/expenses/status" method="POST" port="${http.port}" connector-ref="httpConnector"/> <!--注释3 发送JMS消息到话题--> <jms:outbound-endpoint topic="expenses.status"/> </flow>
JMS 代理配置上有少许不同。你需要显性的为代理配置连接器。注释1处,是使用一个外部的ActiveMQ 实例。代理的URL设置成了属性值${jms.url}。JMS的规范版本也在这里进行了声明。如果你想使用 1.0.2b规范,你只需简单的把 1.1 改为 1.0.2b即可。HTTP inbound endpoint配置在注释2处,这里没变。
JMS endpoint配置在注释3处。来自 inbound endpoint的的字符串将以JMS TextMessage的形式发送到expenses.status 话题。
JMS传输将根据源数据创建特定类型的JMS 消息。byte数组将转换为 BytesMessage,map转换为
MapMessage ,输入转换为StreamMessage,对象转换为ObjectMessage,String转换为TextMessage。
向队列发送消息非常简单,你只需把 topic 属性改为 queue就行。如下所示:
<jms:outbound-endpoint queue="expenses.status"/>
现在通过这个endpoint发送的消息将放到 一个叫做expenses.status的队列中。
在endpoint指定JMS连接器 若你使用URI指定JMS目的地(如jms://expenses.status),
你可以通过追加 ?connector-ref=connector-name来标示这个连接器。
例如,前例中的outbound endpoint 的URI 将是:
jms://expenses.status?connector=jmsConnector 。当对一个传输指定多个连接器时,
这种语法是很有用的。
3.4.2 使用JMS inbound endpoint接受JMS消息
列表3.15 描述了你向其发布消息的话题(见前一个列表),这里会对处理完的支出报表 记录日志。
(见图3.12)
Listing 3.15 Logging JMS messages published to a topic
<flow name="logExpenseReports"> <!--注释1 接收expenses.status topic的消息 --> <jms:inbound-endpoint topic="expenses.status" exchange-pattern="one-way"/> <logger level="INFO" message="Expense Report Processed: #[org.mule.util.DateUtils.getTimeStamp('dd-MM-yy_HH-mm-ss.SSS')]"/> </flow>
inbound endpoint 配置在注释1处。它将从话题expenses.status消费消息。
日志消息处理器通过mule日志工具记录消息。第8章详解。
你可以在inbound endpoint进行话题订阅的持久化。通过配置连接器实现持久化,
如下:
<jms:activemq-connector name="jmsConnector" specification="1.1" brokerURL="tcp://mq.prancingdonkey.com:61616" durable="true" />
3.4.3 在JMS endpoint使用过滤器
过滤器可以用在 JMS endpoint以筛选消费的消息。JMS inbound endpoint过滤器通过使用JMS选择器设施完成来完成。根据列表3.15 修改JMS inbound endpoint只接受2012年1月1日0点之后创建的通知。
Listing 3.16 Using a JMS selector filter to choose the messages an endpoint receives
<jms:inbound-endpoint topic="expenses.status"> <!--定义 JMS选择器--> <jms:selector expression="JMSTimestamp >1325376000000" /> </jms:inbound-endpoint>
你可以在任何头属性中这样使用JMS选择器。你可能好奇注释1处 使用的 > 。
这是xml对 > 的转义。不正确转义 > 将会导致mule启动时的xml解析错误。
3.4.4 同步的使用 JMS
异步是JMS固有特性,经常在inbound endpoint使用 单向的消息交换方式--发出消息并不等待回应。
但有时你想等待一个消息的响应。这可通过设置inbound endpoint 的消息交换方式为 请求-响应式来完成。
下面通过调用 BrewServiceImpl的 getBrews()方法来展示,见下列表(见图3.13)
Listing 3.17 Synchronously invoke a component using JMS
<flow name="brewJmsService"> <!--使用 jms inbound endpoint代替 HTTP --> <jms:inbound-endpoint queue="brews.list" exchange-pattern="request-response"/> <component class="com.prancingdonkey.service.BrewServiceImpl"/> <mule-xml:object-to-xml-transformer /> </flow>
JMS inbound endpoin的请求-响应式的消息交换方式,说明会期待返回响应。为了实现这种方式,JMS传输将对响应数据创建一个临时的队列,并把JMS响应消息的Reply-To属性设置为队列名字。
学会在Mule中使用JMS 在应用集成中是非常重要的。你只需要知道如何使用JMS endpoint向
JMS 队列或话题发送和接受数据即可。