快速了解使用 Spring JMS 框架和 IBM WebSphere MQ 5.3 進(jìn)行 JMS 消息處理的基礎(chǔ)知識(shí)。
在 Spring 系列 的第 4 期也是最后一期中,我將介紹 Spring JMS(Java 消息服務(wù))框架的特性。JMS PG 定義了 Java 應(yīng)用程序通過(guò)面向消息的中間件(MOM)創(chuàng)建和交換消息的標(biāo)準(zhǔn)途徑。
就像在這個(gè)系列前面的文章中一樣,我將使用一個(gè)簡(jiǎn)單的示例來(lái)演示 Spring JMS 的特性。您將隨我一道開(kāi)發(fā)一個(gè)點(diǎn)對(duì)點(diǎn)的(P2P)基于消息的系統(tǒng),使用 Spring JMS 框架通過(guò) JMS 接口與 IBM 的 WebSphere MQ 集成。完成練習(xí)后,將可以通過(guò)這個(gè)系統(tǒng)發(fā)送和接收簡(jiǎn)單的文本消息。
在開(kāi)始之前,請(qǐng) 下載文章的源代碼。請(qǐng)參閱 參考資料 訪(fǎng)問(wèn) Spring 框架和 IBM WebSphere MQ 5.3。還需要 Apache Ant 來(lái)運(yùn)行示例應(yīng)用程序。
Spring 的 JMS 抽象框架簡(jiǎn)化了 JMS API 的使用,并與 JMS 提供者(比如 IBM 的 WebSphere MQ 5.3)平滑地集成。org.springframework.jms.core 包提供了在 Spring 中使用 JMS 的核心功能。它的模板類(lèi)處理資源的創(chuàng)建和釋放,簡(jiǎn)化了 JMS 的使用。
像其他大多數(shù) Spring 模板類(lèi)一樣,JMS 模板類(lèi)提供了執(zhí)行公共操作的 helper 方法。在需要更復(fù)雜應(yīng)用的情況下,類(lèi)把處理任務(wù)的核心委托給用戶(hù)實(shí)現(xiàn)的回調(diào)接口。JMS 類(lèi)提供了方便的方法,用來(lái)發(fā)送消息、同步地使用消息以及向用戶(hù)公開(kāi) JMS 會(huì)話(huà)和消息的制作者。
以下 JMS 包和 org.springframework.jms.core 一起構(gòu)成了 Spring JMS 的功能:
JMSException
的功能。轉(zhuǎn)換代碼把檢測(cè)到的 JMSException
層次結(jié)構(gòu)轉(zhuǎn)換成未檢測(cè)到異常的鏡像層次結(jié)構(gòu)。MessageConverter
抽象,以在 Java 對(duì)象和 JMS 消息之間進(jìn)行轉(zhuǎn)換。ConnectionFactory
實(shí)現(xiàn)。connection 還包含針對(duì) JMS 的 Spring PlatformTransactionManager
實(shí)現(xiàn)。它允許把 JMS 作為事務(wù)性資源集成到 Spring 的事務(wù)管理機(jī)制中。 ![]() ![]() |
![]()
|
就像前面提到的,示例應(yīng)用程序會(huì)用 Spring 的 JMS 框架通過(guò) JMS 接口與 IBM 的 WebSphere MQ 集成。通過(guò)在應(yīng)用程序和 Web 服務(wù)之間傳遞消息,WebSphere MQ 提供了可靠的、有恢復(fù)能力的應(yīng)用程序集成。它使用隊(duì)列和事務(wù)性工具幫助保持消息跨網(wǎng)絡(luò)的完整性。WebSphere MQ 降低了信息丟失的風(fēng)險(xiǎn)和調(diào)和通信 IT 系統(tǒng)的需要。
WebSphere MQ 在它所支持的所有平臺(tái)上提供了一致的應(yīng)用程序編程接口,這有助于讓集成的程序可移植。除了標(biāo)準(zhǔn)接口外,WebSphere MQ 還完整實(shí)現(xiàn)了JMS 接口,包括對(duì)發(fā)布-訂閱消息傳遞的支持。WebSphere MQ Explorer 工具可以遠(yuǎn)程地管理和配置整個(gè) MQ 網(wǎng)絡(luò)。管理和配置工具基于開(kāi)放源碼的 Eclipse 框架,而且是可擴(kuò)展的。
![]() ![]() |
![]()
|
Spring 框架提供了 JmsTemplate
的兩個(gè)實(shí)現(xiàn)。JmsTemplate
類(lèi)使用 JMS 1.1 API,子類(lèi) JmsTemplate102
則使用 JMS 1.0.2 API。我的示例應(yīng)用程序使用的是 JmsTemplate102
。
JMS 模板被用來(lái)發(fā)送和接收 JMS 消息。Spring 采用回調(diào)機(jī)制對(duì) JMS 信息傳遞進(jìn)行協(xié)調(diào)。MessageCreator
回調(diào)接口用 JmsTemplate
中的調(diào)用代碼提供的 Session
創(chuàng)建消息。為了支持 JMS API 更復(fù)雜的應(yīng)用,回調(diào) SessionCallback
向用戶(hù)提供了 JMS 會(huì)話(huà),而 callback ProducerCallback
則公開(kāi)了 Session
和 MessageProducer
組合。
清單 1 顯示了示例應(yīng)用程序使用的 JMS 模板的配置。清單摘自 spring-mqseries-jms.xml 文件(請(qǐng)參閱 下載)。
<!-- JMS Queue Template --> <bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate102"> <property name="connectionFactory"> <ref bean="jmsQueueConnectionFactory"/> </property> <property name="destinationResolver"> <ref bean="jmsDestinationResolver"/> </property> <property name="pubSubDomain"> <value>false</value> </property> <property name="receiveTimeout"> <value>20000</value> </property> </bean> |
jmsQueueTemplate
bean 與 JMS 連接工廠(chǎng)和 JMS 目標(biāo)解析器綁定在一起,用于解析 JMS 客戶(hù)機(jī)通過(guò) JNDI 提供的目標(biāo)隊(duì)列名。connectionFactory
屬性指定了如何獲得到 JMS 提供者的連接。在本例中,清單 2 顯示了如何從 JNDI 檢索連接工廠(chǎng)。
<!-- JMS Queue Connection Factory --> <bean id="internalJmsQueueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiTemplate"> <ref bean="jndiTemplate"/> </property> <property name="jndiName"> <value>MQ_JMS_MANAGER</value> </property> </bean> |
可以看到,JndiObjectFactoryBean
被綁定到 internalJmsQueueConnectionFactory
。JndiObjectFactoryBean
用 JndiTemplate
屬性進(jìn)行 JNDI 查詢(xún)。Spring 將用 JndiTemplate
中指定的環(huán)境屬性和初始上下文在 JNDI 中查詢(xún)連接工廠(chǎng)。清單 3 顯示了 JndiTemplate
配置 bean 的配置。
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate"> <property name="environment"> <props> <prop key="java.naming.factory.initial"> com.sun.jndi.fscontext.RefFSContextFactory </prop> <prop key="java.naming.provider.url"> file:/C:/JNDI-Directory </prop> </props> </property> </bean> |
以上配置進(jìn)行 JNDI 查詢(xún)時(shí)用 com.sun.jndi.fscontext.RefFSContextFactory
指定初始上下文工廠(chǎng),用基于文件的 file:/C:/JNDI-Directory 作為提供者 URL。根據(jù)示例應(yīng)用程序的意圖,JNDI 訪(fǎng)問(wèn)會(huì)采用基于文件的 FSContext
版本(請(qǐng)參閱 參考資料)的配置把 MQ 隊(duì)列綁定到 JNDI。
有了定義好的 JMS 模板,下一步就是把它綁定到示例應(yīng)用程序中,然后就可以用它發(fā)送和接收消息了。
![]() ![]() |
![]()
|
JMS 模板可以綁定到應(yīng)用程序中,以發(fā)送和接收 JMS 消息。在清單 4 中可以看出我如何把 清單 1 中的 JMS 模板綁定到示例應(yīng)用程序中。
<bean id="jmsSender" class="springexample.client.JMSSender"> <property name="jmsTemplate102"> <ref bean="jmsQueueTemplate"/> </property> </bean> <bean id="jmsReceiver" class="springexample.client.JMSReceiver"> <property name="jmsTemplate102"> <ref bean="jmsQueueTemplate"/> </property> </bean> |
可以看到,我把 jmsQueueTemplate
綁定到用來(lái)發(fā)送和接收消息的 JmsSender
應(yīng)用程序 bean 和 JmsReceiver
bean。清單 5 顯示了與 JMSSender
類(lèi)有關(guān)的代碼。
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
類(lèi)用 jmsTemplate102.send()
方法發(fā)送 JMS 消息。send()
方法的第一個(gè)參數(shù)是 JNDI 隊(duì)列名,隊(duì)列名指定了消息應(yīng)當(dāng)發(fā)送到哪里。(很快就會(huì)看到如何把 WebSphere MQ 的隊(duì)列名綁定到 JNDI。)send()
方法的第二個(gè)參數(shù)是 MessageCreator
類(lèi)。JmsTemplate
中的調(diào)用代碼提供了 Session
類(lèi),這個(gè)類(lèi)提供了一個(gè)創(chuàng)建 JMS 消息的回調(diào)接口。
下一步是用 JMS 的 Session
類(lèi)創(chuàng)建一個(gè)簡(jiǎn)單的文本消息。在代碼執(zhí)行時(shí),消息會(huì)傳遞給 WebSphere MQ 服務(wù)器的隊(duì)列。清單 6 顯示了使用 JmsTemplate
檢索 JMS 消息的 JMSReceiver
應(yīng)用程序 bean 的代碼。
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
類(lèi)用 jmsTemplate102.receive()
方法同步地接收 JMS 消息。receive()
方法指定 JNDI 隊(duì)列名,并從中檢索消息。JMSTemplate
類(lèi)的 processMessage()
方法由接收 JMS 客戶(hù)機(jī)調(diào)用。JSMTemplate
bean 的屬性 receiveTimeout(列在 JMSTemplate
配置中)指定接收客戶(hù)機(jī)同步地從隊(duì)列中接收消息時(shí)要等候的時(shí)間。
現(xiàn)在應(yīng)用程序的代碼已完成!下一步就是配置 WebSphere MQ 隊(duì)列并把它們綁定到 JNDI 對(duì)象。
![]() ![]() |
![]()
|
在運(yùn)行應(yīng)用程序之前,需要設(shè)置 WebSphere MQ 的隊(duì)列管理器和隊(duì)列,并把它們綁定到 JNDI。如果喜歡的話(huà),可以按照這部分的示例做:只需 下載 設(shè)置 WebSphere MQ 隊(duì)列的批文件和應(yīng)用程序的源代碼和部署描述符即可。把 zip 文件解壓到驅(qū)動(dòng)器 C:。
設(shè)置隊(duì)列
運(yùn)行 C:\SpringSeriesPart4JMS\batch 文件夾中的 mqsetup.bat 文件。這個(gè)批文件要求在 path 環(huán)境變量中設(shè)置好 MQ 安裝的 bin 文件夾(例如 C:\mqseries\bin)。運(yùn)行了批文件之后,應(yīng)當(dāng)看到消息 “All valid MQSC commands were processed
”。要打開(kāi) MQ Explorer 并檢查已經(jīng)創(chuàng)建的隊(duì)列管理器和隊(duì)列,請(qǐng)選擇 Start -> Programs -> IBM MQSeries -> MQSeriesExplorer。圖 1 顯示出示例應(yīng)用程序 QueueManager
MQJMS.QManager
已經(jīng)創(chuàng)建并正在運(yùn)行。
請(qǐng)?jiān)趹?yīng)用程序屏幕左側(cè)面板上點(diǎn)擊 MQJMS.QManager
下的 Queues 文件夾。應(yīng)當(dāng)看到已經(jīng)創(chuàng)建了一個(gè)隊(duì)列 RequestResponseQueue
,如圖 2 所示。
這就完成了隊(duì)列的設(shè)置。
設(shè)置 JMS 和 JNDI 管理
在示例應(yīng)用程序中,JNDI 的訪(fǎng)問(wèn)利用了可以從 JNDI 主頁(yè)得到的基于文件的 FSContext
版本(請(qǐng)參閱 參考資料)。FSContext.jar 文件也包含在 WebSphere MQ 的 JMS 支持當(dāng)中。請(qǐng)?zhí)砑游募A \MQSeriesInstallable\MQSeries\Java\lib 和 \MQSeriesInstallable\MQSeries\Java\bin 到系統(tǒng)的 PATH 環(huán)境變量中。而且,請(qǐng)把 \MQSeriesInstallable\MQSeries\Java\lib 文件夾中的所有 jar 文件添加到系統(tǒng)的 CLASSPATH 環(huán)境變量中。還可以運(yùn)行 C:\SpringSeriesPart4JMS\batch 文件夾中的 classpath.cmd 文件,它會(huì)設(shè)置必要的 path 和 CLASSPATH 變量。要做到這點(diǎn),只需要修改 classpath.cmd 文件中的 MQ_JAVA_INSTALL_PATH
,把它指到 WebSphere MQ JMS 的安裝目錄。
接下來(lái),修改 \MQSeriesInstallableDirectory\Java\bin 中的 JMSAdmin.config 配置文件,MQSeries JMS 管理程序用它指明應(yīng)用程序要使用的上下文工廠(chǎng)和 JNDI 實(shí)現(xiàn)的地址。請(qǐng)取消以下行的注釋?zhuān)?/p>
INITIAL_CONTEXT_FACTORY=com.sun.jndi.fscontext.RefFSContextFactory |
并注釋掉其余兩個(gè) INITIAL_CONTEXT_FACTORY
變量。還要取消以下行的注釋?zhuān)?/p>
PROVIDER_URL=file:/C:/JNDI-Directory |
并注釋掉其余兩個(gè) PROVIDER_URL
變量。
可以在 C:\SpringSeriesPart4JMS\batch 文件夾中發(fā)現(xiàn)參考的示例配置文件。
為了保存 JNDI 對(duì)象,請(qǐng)?jiān)隍?qū)動(dòng)器 C: 上創(chuàng)建名為 JNDI-Directory 的目錄。切換到 \MQSeriesInstallableDirectory\Java\bin 目錄并運(yùn)行 JMSAdmin 批文件,應(yīng)當(dāng)看到 InitCtx 變量。
逐個(gè)輸入以下內(nèi)容:
def qcf(MQ_JMS_MANAGER) qmgr(MQJMS.QManager) |
現(xiàn)在已經(jīng)把 WebSphere MQ 隊(duì)列綁定到 JNDI 對(duì)象,作為應(yīng)用程序客戶(hù)可以通過(guò) JNDI 查詢(xún)對(duì)象?,F(xiàn)在剩下的就是看代碼的實(shí)際作用了!
![]() ![]() |
![]()
|
要運(yùn)行示例,請(qǐng)從 spring sourceforge download 下載 Spring 框架和它的所有依賴(lài)文件并解壓,例如解壓到 c:\。會(huì)創(chuàng)建文件夾 C:\spring-framework-1.2-rc2(或最新版本)。
要運(yùn)行 Spring 應(yīng)用程序,請(qǐng)把本文的源代碼解壓到任意文件夾,例如 c:\。會(huì)創(chuàng)建文件夾 SpringSeriesPart4JMS。就像前面提到過(guò)的,還需要安裝 Apache Ant 和它的 Spring 依賴(lài) jar 文件。請(qǐng)把 Spring 庫(kù) —— 即 spring.jar(在 C:\spring-framework-1.2-rc2\dist 中)和 commons-logging.jar(在 C:\spring-framework-1.2-rc2\lib\jakarta-commons 中)拷貝到 SpringSeriesPart4JMS\lib 文件夾。還要把所有的 jar 庫(kù)從 \MQSeriesInstallableDirectory\Java\lib 目錄拷貝到 SpringSeriesPart4JMS\lib 文件夾。其中包含 MQseries 和 JMS 的相關(guān)庫(kù)?,F(xiàn)在就擁有了構(gòu)建的依賴(lài)集。
接下來(lái),打開(kāi)命令提示符,切換到 SpringProject4 目錄,并在命令提示符下輸入以下命令:
> ant -f build-jmssender.xml. |
這會(huì)構(gòu)建并運(yùn)行 SendMQSpringJMS
類(lèi),它會(huì)調(diào)用 JMSSender
類(lèi),發(fā)送消息到 WebSphere MQ RequestResponse
隊(duì)列。SendMQSpringJMS
還會(huì)通過(guò)它的 ClassPathXmlApplicationContext
裝入 spring 配置文件。一旦 bean 全部裝載,就可以通過(guò) Spring 的 ApplicationContext 的 getBean()
方法訪(fǎng)問(wèn) JMSSender(請(qǐng)參閱清單 7)。
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] { "spring-mqseries-jms.xml" }); JMSSender jmsSender = (JMSSender) appContext.getBean("jmsSender"); |
消息傳遞到隊(duì)列上之后,請(qǐng)運(yùn)行 JMS 接收方客戶(hù)機(jī)以檢索消息。請(qǐng)打開(kāi)命令提示符,切換到目錄 SpringProject4,并輸入:
> ant -f build-jmsreceiver.xml |
這會(huì)構(gòu)建并運(yùn)行 ReceiveMQSpringJMS
類(lèi),該類(lèi)會(huì)調(diào)用 JMSReceiver
類(lèi),以從 WebSphere MQ 的 RequestResponse
隊(duì)列接收文本消息。在控制臺(tái)上會(huì)打印出以下消息:
Message Received --> This is a sample message. |
在 Spring 系列的最后這篇文章中,您學(xué)習(xí)了 Spring JMS 框架的基礎(chǔ)。我首先介紹了示例應(yīng)用程序的核心組件 —— Spring JMS 框架和 IBM 的 WebSphere MQ 5.3,然后介紹了如何用 Spring JMS 模板向 WebSphere MQ 隊(duì)列發(fā)送消息和從中接收消息。雖然這個(gè)示例非常簡(jiǎn)單,但是可以把這里介紹的步驟應(yīng)用到更復(fù)雜的應(yīng)用程序。
聯(lián)系客服