程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Spring系列,第4部分: Spring JMS消息處理1-2-3

Spring系列,第4部分: Spring JMS消息處理1-2-3

編輯:關於JAVA

快速了解使用 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

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 的 Spring PlatformTransactionManager 實現。它允許把 JMS 作為事務性資源集成到 Spring 的事務管理機制中。

IBM WebSphere MQ

就像前面提到的,示例應用程序會用 Spring 的 JMS 框架通過 JMS 接口與 IBM 的 WebSphere MQ 集成。通過在應用程序和 Web 服務之間傳遞消息,WebSphere MQ 提供了可靠的、有恢復能力的應用程序集成。它使用隊列和事務性工具幫助保持消息跨網絡的完整性。WebSphere MQ 降低了信息丟失的風險和調和通信 IT 系統的需要。

WebSphere MQ 在它所支持的所有平台上提供了一致的應用程序編程接口,這有助於讓集成的程序可移植。除了標准接口外,WebSphere MQ 還完整實現了JMS 接口,包括對發布-訂閱消息傳遞的支持。WebSphere MQ Explorer 工具可以遠程地管理和配置整個 MQ 網絡。管理和配置工具基於開放源碼的 Eclipse 框架,而且是可擴展的。

Spring JMS 模板

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 模板,下一步就是把它綁定到示例應用程序中,然後就可以用它發送和接收消息了。

Spring 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)
按回車
def q(JMS_RequestResponseQueue) qmgr(MQJMS.QManager)
        queue(RequestResponseQueue)
按回車

現在已經把 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 的內容。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved