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 隊列或話題發送和接受資料即可。