快速了解使用 Spring JMS 框架和 IBM WebSphere MQ 5.3 進行 JMS 消息處理的基礎知識。
在 Spring 系列 的第 4 期也是最后一期中,我將介紹 Spring JMS(Java 消息服務)框架的特性。JMS PG 定義了 Java 應用程序通過面向消息的中間件(MOM)創建和交換消息的標準途徑。
就像在這個系列前面的文章中一樣,我將使用一個簡單的示例來演示 Spring JMS 的特性。您將隨我一道開發一個點對點的(P2P)基于消息的系統,使用 Spring JMS 框架通過 JMS 接口與 IBM 的 WebSphere MQ 集成。完成練習后,將可以通過這個系統發送和接收簡單的文本消息。
在開始之前,請 下載文章的源代碼。請參閱 參考資料 訪問 Spring 框架和 IBM WebSphere MQ 5.3。還需要 Apache Ant 來運行示例應用程序。
Spring 的 JMS 抽象框架簡化了 JMS API 的使用,并與 JMS 提供者(比如 IBM 的 WebSphere MQ 5.3)平滑地集成。org.springframework.jms.core 包提供了在 Spring 中使用 JMS 的核心功能。它的模板類處理資源的創建和釋放,簡化了 JMS 的使用。
像其他大多數 Spring 模板類一樣,JMS 模板類提供了執行公共操作的 helper 方法。在需要更復雜應用的情況下,類把處理任務的核心委托給用戶實現的回調接口。JMS 類提供了方便的方法,用來發送消息、同步地使用消息以及向用戶公開 JMS 會話和消息的制作者。
以下 JMS 包和 org.springframework.jms.core 一起構成了 Spring JMS 的功能:
- org.springframework.jms.support
- 提供轉換
JMSException
的功能。轉換代碼把檢測到的JMSException
層次結構轉換成未檢測到異常的鏡像層次結構。 - org.springframework.jms.support.converter
- 提供
MessageConverter
抽象,以在 Java 對象和 JMS 消息之間進行轉換。 - org.springframework.jms.support.destination
- 提供管理 JMS 目標的不同策略,比如針對 JNDI 中保存的目標的服務定位器。
- org.springframework.jms.connection
- 提供適合在獨立應用程序中使用的
ConnectionFactory
實現。connection 還包含針對 JMS 的 SpringPlatformTransactionManager
實現。它允許把 JMS 作為事務性資源集成到 Spring 的事務管理機制中。
![]() ![]() |
![]()
|
就像前面提到的,示例應用程序會用 Spring 的 JMS 框架通過 JMS 接口與 IBM 的 WebSphere MQ 集成。通過在應用程序和 Web 服務之間傳遞消息,WebSphere MQ 提供了可靠的、有恢復能力的應用程序集成。它使用隊列和事務性工具幫助保持消息跨網絡的完整性。WebSphere MQ 降低了信息丟失的風險和調和通信 IT 系統的需要。
WebSphere MQ 在它所支持的所有平臺上提供了一致的應用程序編程接口,這有助于讓集成的程序可移植。除了標準接口外,WebSphere MQ 還完整實現了JMS 接口,包括對發布-訂閱消息傳遞的支持。WebSphere MQ Explorer 工具可以遠程地管理和配置整個 MQ 網絡。管理和配置工具基于開放源碼的 Eclipse 框架,而且是可擴展的。
![]() ![]() |
![]()
|
Spring 框架提供了 JmsTemplate
的兩個實現。JmsTemplate
類使用 JMS 1.1 API,子類 JmsTemplate102
則使用 JMS 1.0.2 API。我的示例應用程序使用的是 JmsTemplate102
。
JMS 模板被用來發送和接收 JMS 消息。Spring 采用回調機制對 JMS 信息傳遞進行協調。MessageCreator
回調接口用 JmsTemplate
中的調用代碼提供的 Session
創建消息。為了支持 JMS API 更復雜的應用,回調 SessionCallback
向用戶提供了 JMS 會話,而 callback ProducerCallback
則公開了 Session
和 MessageProducer
組合。
清單 1 顯示了示例應用程序使用的 JMS 模板的配置。清單摘自 spring-mqseries-jms.xml 文件(請參閱 下載)。
清單 1. JMS 模板配置
<!-- 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 連接工廠和 JMS 目標解析器綁定在一起,用于解析 JMS 客戶機通過 JNDI 提供的目標隊列名。connectionFactory
屬性指定了如何獲得到 JMS 提供者的連接。在本例中,清單 2 顯示了如何從 JNDI 檢索連接工廠。
清單 2. 通過 JNDI 配置 JMS 連接工廠
<!-- 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
屬性進行 JNDI 查詢。Spring 將用 JndiTemplate
中指定的環境屬性和初始上下文在 JNDI 中查詢連接工廠。清單 3 顯示了 JndiTemplate
配置 bean 的配置。
清單 3. JNDI 查詢的 JNDI 模板配置
<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> |
以上配置進行 JNDI 查詢時用 com.sun.jndi.fscontext.RefFSContextFactory
指定初始上下文工廠,用基于文件的 file:/C:/JNDI-Directory 作為提供者 URL。根據示例應用程序的意圖,JNDI 訪問會采用基于文件的 FSContext
版本(請參閱 參考資料)的配置把 MQ 隊列綁定到 JNDI。
有了定義好的 JMS 模板,下一步就是把它綁定到示例應用程序中,然后就可以用它發送和接收消息了。
![]() ![]() |
![]()
|
JMS 模板可以綁定到應用程序中,以發送和接收 JMS 消息。在清單 4 中可以看出我如何把 清單 1 中的 JMS 模板綁定到示例應用程序中。
清單 4. 把 JmsTemplate 綁定到應用程序中
<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
綁定到用來發送和接收消息的 JmsSender
應用程序 bean 和 JmsReceiver
bean。清單 5 顯示了與 JMSSender
類有關的代碼。
清單 5. 用 JmsTemplate 發送 JMS 消息的 JMSSender
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
類用 jmsTemplate102.send()
方法發送 JMS 消息。send()
方法的第一個參數是 JNDI 隊列名,隊列名指定了消息應當發送到哪里。(很快就會看到如何把 WebSphere MQ 的隊列名綁定到 JNDI。)send()
方法的第二個參數是 MessageCreator
類。JmsTemplate
中的調用代碼提供了 Session
類,這個類提供了一個創建 JMS 消息的回調接口。
下一步是用 JMS 的 Session
類創建一個簡單的文本消息。在代碼執行時,消息會傳遞給 WebSphere MQ 服務器的隊列。清單 6 顯示了使用 JmsTemplate
檢索 JMS 消息的 JMSReceiver
應用程序 bean 的代碼。
清單 6. 用 JmsTemplate 檢索 JMS 消息的 JMSReceiver
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
類用 jmsTemplate102.receive()
方法同步地接收 JMS 消息。receive()
方法指定 JNDI 隊列名,并從中檢索消息。JMSTemplate
類的 processMessage()
方法由接收 JMS 客戶機調用。JSMTemplate
bean 的屬性 receiveTimeout(列在 JMSTemplate
配置中)指定接收客戶機同步地從隊列中接收消息時要等候的時間。
現在應用程序的代碼已完成!下一步就是配置 WebSphere MQ 隊列并把它們綁定到 JNDI 對象。
![]() ![]() |
![]()
|
在運行應用程序之前,需要設置 WebSphere MQ 的隊列管理器和隊列,并把它們綁定到 JNDI。如果喜歡的話,可以按照這部分的示例做:只需 下載 設置 WebSphere MQ 隊列的批文件和應用程序的源代碼和部署描述符即可。把 zip 文件解壓到驅動器 C:。
設置隊列
運行 C:\SpringSeriesPart4JMS\batch 文件夾中的 mqsetup.bat 文件。這個批文件要求在 path 環境變量中設置好 MQ 安裝的 bin 文件夾(例如 C:\mqseries\bin)。運行了批文件之后,應當看到消息 “All valid MQSC commands were processed
”。要打開 MQ Explorer 并檢查已經創建的隊列管理器和隊列,請選擇 Start -> Programs -> IBM MQSeries -> MQSeriesExplorer。圖 1 顯示出示例應用程序 QueueManager
MQJMS.QManager
已經創建并正在運行。
圖 1. WebSphere MQ 的 QueueManager 配置

請在應用程序屏幕左側面板上點擊 MQJMS.QManager
下的 Queues 文件夾。應當看到已經創建了一個隊列 RequestResponseQueue
,如圖 2 所示。
圖 2. WebSphere MQ 的請求/響應隊列配置

這就完成了隊列的設置。
設置 JMS 和 JNDI 管理
在示例應用程序中,JNDI 的訪問利用了可以從 JNDI 主頁得到的基于文件的 FSContext
版本(請參閱 參考資料)。FSContext.jar 文件也包含在 WebSphere MQ 的 JMS 支持當中。請添加文件夾 \MQSeriesInstallable\MQSeries\Java\lib 和 \MQSeriesInstallable\MQSeries\Java\bin 到系統的 PATH 環境變量中。而且,請把 \MQSeriesInstallable\MQSeries\Java\lib 文件夾中的所有 jar 文件添加到系統的 CLASSPATH 環境變量中。還可以運行 C:\SpringSeriesPart4JMS\batch 文件夾中的 classpath.cmd 文件,它會設置必要的 path 和 CLASSPATH 變量。要做到這點,只需要修改 classpath.cmd 文件中的 MQ_JAVA_INSTALL_PATH
,把它指到 WebSphere MQ JMS 的安裝目錄。
接下來,修改 \MQSeriesInstallableDirectory\Java\bin 中的 JMSAdmin.config 配置文件,MQSeries JMS 管理程序用它指明應用程序要使用的上下文工廠和 JNDI 實現的地址。請取消以下行的注釋:
INITIAL_CONTEXT_FACTORY=com.sun.jndi.fscontext.RefFSContextFactory |
并注釋掉其余兩個 INITIAL_CONTEXT_FACTORY
變量。還要取消以下行的注釋:
PROVIDER_URL=file:/C:/JNDI-Directory |
并注釋掉其余兩個 PROVIDER_URL
變量。
可以在 C:\SpringSeriesPart4JMS\batch 文件夾中發現參考的示例配置文件。
為了保存 JNDI 對象,請在驅動器 C: 上創建名為 JNDI-Directory 的目錄。切換到 \MQSeriesInstallableDirectory\Java\bin 目錄并運行 JMSAdmin 批文件,應當看到 InitCtx 變量。
逐個輸入以下內容:
def qcf(MQ_JMS_MANAGER) qmgr(MQJMS.QManager) |
現在已經把 WebSphere MQ 隊列綁定到 JNDI 對象,作為應用程序客戶可以通過 JNDI 查詢對象。現在剩下的就是看代碼的實際作用了!
![]() ![]() |
![]()
|
要運行示例,請從 spring sourceforge download 下載 Spring 框架和它的所有依賴文件并解壓,例如解壓到 c:\。會創建文件夾 C:\spring-framework-1.2-rc2(或最新版本)。
要運行 Spring 應用程序,請把本文的源代碼解壓到任意文件夾,例如 c:\。會創建文件夾 SpringSeriesPart4JMS。就像前面提到過的,還需要安裝 Apache Ant 和它的 Spring 依賴 jar 文件。請把 Spring 庫 —— 即 spring.jar(在 C:\spring-framework-1.2-rc2\dist 中)和 commons-logging.jar(在 C:\spring-framework-1.2-rc2\lib\jakarta-commons 中)拷貝到 SpringSeriesPart4JMS\lib 文件夾。還要把所有的 jar 庫從 \MQSeriesInstallableDirectory\Java\lib 目錄拷貝到 SpringSeriesPart4JMS\lib 文件夾。其中包含 MQseries 和 JMS 的相關庫。現在就擁有了構建的依賴集。
接下來,打開命令提示符,切換到 SpringProject4 目錄,并在命令提示符下輸入以下命令:
> ant -f build-jmssender.xml. |
這會構建并運行 SendMQSpringJMS
類,它會調用 JMSSender
類,發送消息到 WebSphere MQ RequestResponse
隊列。SendMQSpringJMS
還會通過它的 ClassPathXmlApplicationContext
裝入 spring 配置文件。一旦 bean 全部裝載,就可以通過 Spring 的 ApplicationContext 的 getBean()
方法訪問 JMSSender(請參閱清單 7)。
清單 7. 裝入示例應用程序的 Spring 配置
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] { "spring-mqseries-jms.xml" }); JMSSender jmsSender = (JMSSender) appContext.getBean("jmsSender"); |
消息傳遞到隊列上之后,請運行 JMS 接收方客戶機以檢索消息。請打開命令提示符,切換到目錄 SpringProject4,并輸入:
> ant -f build-jmsreceiver.xml |
這會構建并運行 ReceiveMQSpringJMS
類,該類會調用 JMSReceiver
類,以從 WebSphere MQ 的 RequestResponse
隊列接收文本消息。在控制臺上會打印出以下消息:
Message Received --> This is a sample message. |
在 Spring 系列的最后這篇文章中,您學習了 Spring JMS 框架的基礎。我首先介紹了示例應用程序的核心組件 —— Spring JMS 框架和 IBM 的 WebSphere MQ 5.3,然后介紹了如何用 Spring JMS 模板向 WebSphere MQ 隊列發送消息和從中接收消息。雖然這個示例非常簡單,但是可以把這里介紹的步驟應用到更復雜的應用程序。
我希望介紹 Spring 框架核心模塊的這一系列對您有所幫助。請參閱 參考資料 學習更多有關 Spring 框架和 Spring JMS 的內容。
![]() ![]() |
![]()
|
描述 | 名字 | 大小 | 下載方法 |
---|---|---|---|
Example code, Spring files, and build scripts | wa-spring4-SpringSeriesPart4JMS.zip | 17 KB | ?FTP |
![]() |
||||
![]() |
關于下載方法的信息 |
![]() |
![]() |
Get Adobe? Reader? |
學習
- 您可以參閱本文在 developerWorks 全球站點上的 英文原文。
- “輕量級開發的成功秘訣,第 3 部分: Spring 露出水面”(Bruce Tate,developerWorks,2005 年 6 月):Bruce Tate 介紹了 Spring 作為輕量級容器的意義。
- “Writing Java Message Service programs using WebSphere MQ V5.3”(Willy Farrell,developerWorks,2003 年 10 月):安裝和配置 WebSphere MQ 5.3 以進行 JMS 開發和測試的詳細指導。
- “用 AXIS 編寫 JMS 應用程序”(Naveen Balani,developerWorks,2003 年 2 月):開發同步 JMS SOAP 應用程序。
- Web 架構專區 :數百篇涉及基于 Web 的解決方案的文章。
獲得產品和技術
-
Spring 主頁
:下載 Spring 框架。
-
JMS 主頁
:下載 Java 消息服務。
-
JNDI 主頁
:下載 JNDI 和 FSContext。
-
WebSphere MQ
:得到可信的、可靠的 JMS 提供者。
討論
-
參與論壇討論
。
-
developerWorks blogs
:加入 developerWorks 社區。