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

在 Spring 系列 的第 4 期也是最後一期中,我將介紹 Spring JMS(Java 消息服務)框架的特性。JMS PG 定義了 Java 應用程序經過面向消息的中間件(MOM)建立和交換消息的標準途徑。java

就像在這個系列前面的文章中同樣,我將使用一個簡單的示例來演示 Spring JMS 的特性。您將隨我一道開發一個點對點的(P2P)基於消息的系統,使用 Spring JMS 框架經過 JMS 接口與 IBM 的 WebSphere MQ 集成。完成練習後,將能夠經過這個系統發送和接收簡單的文本消息。web

在開始以前,請 下載文章的源代碼。請參閱 參考資料 訪問 Spring 框架和 IBM WebSphere MQ 5.3。還須要 Apache Ant 來運行示例應用程序。spring

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.supportsession

  • 提供轉換 JMSException 的功能。轉換代碼把檢測到的 JMSException 層次結構轉換成未檢測到異常的鏡像層次結構。app

  • org.springframework.jms.support.converter框架

  • 提供 MessageConverter 抽象,以在 Java 對象和 JMS 消息之間進行轉換。jsp

  • 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 被綁定到 internalJmsQueueConnectionFactoryJndiObjectFactoryBean 用 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 顯示出示例應用程序QueueManagerMQJMS.QManager 已經建立並正在運行。

圖 1. WebSphere MQ 的 QueueManager 配置

WebSphere MQ 的 QueueManager 配置

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

圖 2. WebSphere MQ 的請求/響應隊列配置

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 的內容。

相關文章
相關標籤/搜索