posts - 12, comments - 19, trackbacks - 0, articles - 23
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
          異步進(jìn)程通信是面向服務(wù)架構(gòu)(SOA)一個(gè)重要的組成部分,因?yàn)槠髽I(yè)里很多系統(tǒng)通信,特別是與外部組織間的通信,實(shí)質(zhì)上都是異步的。Java消息服務(wù)(JMS)是用于編寫使用異步消息傳遞的JEE應(yīng)用程序的API。傳統(tǒng)的使用JMS API進(jìn)行消息傳遞的實(shí)現(xiàn)包括多個(gè)步驟,例如JNDI查詢隊(duì)列連接工廠和Queue資源,在實(shí)際發(fā)送和接收消息前創(chuàng)建一個(gè)JMS會(huì)話。

             Spring框架則簡(jiǎn)化了使用JEE組件(包括JMS)的任務(wù)。它提供的模板機(jī)制隱藏了典型的JMS實(shí)現(xiàn)的細(xì)節(jié),這樣開發(fā)人員可以集中精力放在處理消息的實(shí)際工作中,而不用擔(dān)心如何去創(chuàng)建,訪問或清除JMS資源。

             本文將對(duì)Spring JMS API作一個(gè)概述,并通過一個(gè)運(yùn)行在JBoss MQ服務(wù)器上的web例程來介紹如何使用Spring JMS API來異步處理(發(fā)送和接收)消息。我將通過傳統(tǒng)JMS實(shí)現(xiàn)和Spring JMS實(shí)現(xiàn)兩者間的比較,來展示使用Spring JMS處理消息是如何的簡(jiǎn)單和靈活。

          異步消息傳遞和面向服務(wù)架構(gòu)

            在現(xiàn)實(shí)中,大多數(shù)web請(qǐng)求都是同步處理的。例如,當(dāng)用戶要登入一個(gè)網(wǎng)站,首先輸入用戶名和密碼,然后服務(wù)器驗(yàn)證登錄合法性。如果驗(yàn)證成功,程序?qū)⒃试S該用戶進(jìn)入網(wǎng)站。這里,登錄請(qǐng)求在從客戶端接收以后被即時(shí)處理了。信用卡驗(yàn)證是另一個(gè)同步處理的例子;只有服務(wù)器證實(shí)輸入的信用卡號(hào)是有效的,同時(shí)客戶在帳戶上有足夠的存款,客戶才被允許繼續(xù)操作。但是讓我們思考一下在順序處理系統(tǒng)上的支付結(jié)算步驟。一旦系統(tǒng)證實(shí)該用戶信用卡的信息是準(zhǔn)確的,并且在帳戶上有足夠的資金,就不必等到所有的支付細(xì)節(jié)落實(shí)、轉(zhuǎn)賬完成。支付結(jié)算可以異步方式進(jìn)行,這樣客戶可以繼續(xù)進(jìn)行核查操作。

             需要比典型同步請(qǐng)求耗費(fèi)更長(zhǎng)時(shí)間的請(qǐng)求,可以使用異步處理。另一個(gè)異步處理的例子是,在本地貸款處理程序中,提交至自動(dòng)承銷系統(tǒng)(AUS)的信用請(qǐng)求處理過程。當(dāng)借方提交貸款申請(qǐng)后,抵押公司會(huì)向AUS發(fā)送請(qǐng)求,以獲取信用歷史記錄。由于這個(gè)請(qǐng)求要求得到全面而又詳細(xì)的信用報(bào)告,包括借方現(xiàn)今和過去的帳戶,最近的付款和其他財(cái)務(wù)資料,服務(wù)器需要耗費(fèi)較長(zhǎng)的時(shí)間(幾小時(shí)或著有時(shí)甚至是幾天)來對(duì)這些請(qǐng)求作出響應(yīng)。客戶端程序(應(yīng)用)要與服務(wù)器連接并耗費(fèi)如此長(zhǎng)的時(shí)間來等待結(jié)果,這是毫無意義的。因此通信應(yīng)該是異步發(fā)生的;也就是,一旦請(qǐng)求被提交,它就被放置在隊(duì)列中,同時(shí)客戶端與服務(wù)器斷開連接。然后AUS服務(wù)從指定的隊(duì)列中選出請(qǐng)求進(jìn)行處理,并將處理得到的消息放置在另一個(gè)消息隊(duì)列里。最后,客戶端程序從這個(gè)隊(duì)列中選出處理結(jié)果,緊接著處理這個(gè)信用歷史數(shù)據(jù)。

          JMS

             如果您使用過JMS代碼,您會(huì)發(fā)現(xiàn)它與JDBC或JCA很像。它所包含的樣本代碼創(chuàng)建或JMS資源對(duì)象回溯,使得每一次您需要寫一個(gè)新類來發(fā)送和接收消息時(shí),都具有更好的代碼密集性和重復(fù)性。以下序列顯示了傳統(tǒng)JMS實(shí)現(xiàn)所包括的步驟:

          1. 創(chuàng)建JNDI初始上下文(context)。
          2. 從JNDI上下文獲取一個(gè)隊(duì)列連接工廠。
          3. 從隊(duì)列連接工廠中獲取一個(gè)Quene。
          4. 創(chuàng)建一個(gè)Session對(duì)象。
          5. 創(chuàng)建一個(gè)發(fā)送者(sender)或接收者(receiver)對(duì)象。
          6. 使用步驟5創(chuàng)建的發(fā)送者或接收者對(duì)象發(fā)送或接收消息。
          7. 處理完消息后,關(guān)閉所有JMS資源。
          您可以看到,步驟6是處理消息的唯一地方。其他步驟都只是管理與實(shí)際業(yè)務(wù)要求無關(guān)的JMS資源,但是開發(fā)人員必須編寫并維護(hù)這些額外步驟的代碼。

          Spring JMS

             Spring框架提供了一個(gè)模板機(jī)制來隱藏Java APIs的細(xì)節(jié)。JEE開發(fā)人員可以使用JDBCTemplate和JNDITemplate類來分別訪問后臺(tái)數(shù)據(jù)庫(kù)和JEE資源(數(shù)據(jù)源,連接池)。JMS也不例外。Spring提供JMSTemplate類,因此開發(fā)人員不用為一個(gè)JMS實(shí)現(xiàn)去編寫樣本代碼。接下來是在開發(fā)JMS應(yīng)用程序時(shí)Spring所具有一些的優(yōu)勢(shì)。

          1. 提供JMS抽象API,簡(jiǎn)化了訪問目標(biāo)(隊(duì)列或主題)和向指定目標(biāo)發(fā)布消息時(shí)JMS的使用。
          2. JEE開發(fā)人員不需要關(guān)心JMS不同版本(例如JMS 1.0.2與JMS 1.1)之間的差異。
          3. 開發(fā)人員不必專門處理JMS異常,因?yàn)镾pring為所有JMS異常提供了一個(gè)未經(jīng)檢查的異常,并在JMS代碼中重新拋出。
          一旦您在JMS應(yīng)用程序中開始使用Spring,您將會(huì)欣賞到它在處理異步消息傳遞上的簡(jiǎn)便。Spring JMS框架提供多種Java類,可以輕松實(shí)現(xiàn)JMS應(yīng)用。表1列出了這些類的一部分。

             表1. Spring JMS類

          類名功能
          JmsExceptionorg.springframework.jms只要發(fā)生一個(gè)JMS異常,Spring框架就會(huì)拋出異常,這個(gè)類是這些所拋出的異常的基(抽象)類。
          JmsTemplate, JmsTemplate102org.springframework.jms.core這些是輔助類,用于簡(jiǎn)化JMS的使用,處理JMS資源(如連接工廠,目標(biāo)和發(fā)送者/接收者對(duì)象)的創(chuàng)建和釋放。JmsTemplate102是JmsTemplate的子類,使用JMS1.0.2規(guī)范
          MessageCreatororg.springframework.jms.core這是JmsTemplate類使用的回叫接口,它為指定的會(huì)話創(chuàng)建JMS消息。
          MessageConverterorg.springframework.jms.support.converter這個(gè)接口充當(dāng)一個(gè)抽象,用來在Java對(duì)象與JMS消息之間進(jìn)行轉(zhuǎn)換。
          DestinationResolverorg.springframework.jms.support.destination這是JmsTemplate用來解析目標(biāo)名的接口。該接口的默認(rèn)實(shí)現(xiàn)是DynamicDestinationResolver和JndiDestinationResolve

            在接下來的部分,我將詳細(xì)解釋表1所列的一部分類(例如JmsTemplate,DestinationResolver和MessageConverter)。

          JMSTemplate

            JmsTemplate提供了幾種輔助方法,用來執(zhí)行一些基本操作。要開始使用JmsTemplate前,您需要知道JMS供應(yīng)商支持哪個(gè)JMS規(guī)范,JBoss AS 4.0.2WebLogic 8.1服務(wù)器支持JMS 1.0.2規(guī)范。WebLogic Server 9.0包括了對(duì)JMS 1.1規(guī)范的支持。JMS 1.1統(tǒng)一了點(diǎn)對(duì)點(diǎn)(PTP)和發(fā)布/訂閱(Pub/Sub)域的編程接口。這種改變的結(jié)果就是,開發(fā)人員可以創(chuàng)建一個(gè)事務(wù)會(huì)話,然后在這同一個(gè)JMS會(huì)話里,可以從一個(gè)Queue(PTP)中接收消息,同時(shí)發(fā)送另一個(gè)消息到一個(gè)Topic(Pub/Sub)。JMS 1.1向后兼容JMS 1.0,應(yīng)此根據(jù)JMS 1.0編寫的代碼仍可以適用于JMS 1.1。

             JmsTemplate提供多種發(fā)送和接收消息的方法。表2列出了這些方法的一部分。

             表2. JMS template方法

          方法名稱功能
          send發(fā)送消息至默認(rèn)或指定的目標(biāo)。JmsTemplate包含send方法,它通過javax.jms.Destination或JNDI查詢來指定目標(biāo)。
          receive從默認(rèn)或指定的目標(biāo)接收消息,但只會(huì)在指定的時(shí)間后傳遞消息。我們可以通過receiveTimeout屬性指定超時(shí)時(shí)間。
          convertAndSend這個(gè)方法委托MessageConverter接口實(shí)例處理轉(zhuǎn)換過程,然后發(fā)送消息至指定的目標(biāo)。
          receiveAndConvert從默認(rèn)或指定的目標(biāo)接收消息。并將消息轉(zhuǎn)換為Java對(duì)象。

            目標(biāo)可以通過JNDI上下文保存和獲取。當(dāng)配置Spring程序上下文(application context)時(shí),我們可以用JndiObjectFactoryBean類取得對(duì)JMS的引用。DestinationResolver接口是用來把目標(biāo)名稱解析成JMS目標(biāo),當(dāng)應(yīng)用程序存在大量目標(biāo)時(shí),這是非常有用的。DynamicDestinationResolver(DestinationResolver的默認(rèn)實(shí)現(xiàn))是用來解析動(dòng)態(tài)目標(biāo)的。

             MessageConverter接口定義了將Java對(duì)象轉(zhuǎn)換為JMS消息的約定。通過這個(gè)轉(zhuǎn)換器,應(yīng)用程序代碼可以集中于處理事務(wù)對(duì)象,而不用為對(duì)象如何表示為JMS消息這樣的內(nèi)部細(xì)節(jié)所困饒。SimpleMessageConverter(和SimpleMessageConverter102)是MessageConverter的默認(rèn)實(shí)現(xiàn)。可使用它們分別將String轉(zhuǎn)換為JMS TextMessage,字節(jié)數(shù)組(byte[])轉(zhuǎn)換為JMS BytesMessage,Map轉(zhuǎn)換為JMS MapMessage,和Serializable對(duì)象轉(zhuǎn)換為JMS ObjectMessage。您也可以編寫自定義的MessageConverter實(shí)例,通過XML綁定框架(例如JAXBCastorCommons DigesterXMLBeansXStream),來實(shí)現(xiàn)XML文檔到TextMessage對(duì)象的轉(zhuǎn)換。

          示例程序

            我將用一個(gè)貸款申請(qǐng)?zhí)幚硐到y(tǒng)(命名為L(zhǎng)oanProc)示例來演示如何在JMS應(yīng)用程序中使用Spring。作為貸款申請(qǐng)的一部分,LoanProc通過發(fā)送貸款詳情(貸款I(lǐng)D,借方名字,借方的SSN,貸款期限和貸款數(shù)額),從AUS系統(tǒng)獲得信用歷史詳情。為了簡(jiǎn)便起見,我們基于兩個(gè)基本參數(shù)來表示信用歷史詳情:信用分?jǐn)?shù)(又名FICO得分)和貸款數(shù)額。讓我們假設(shè)處理信用檢查請(qǐng)求是按以下業(yè)務(wù)規(guī)則進(jìn)行的:

          1. 如果貸款數(shù)額等于或低于$500,000,借方必須至少有一個(gè)"好"的信用(也就是,借方的FICO得分在680到699之間)。
          2. 如果貸款數(shù)額高于$500,000,借方必須至少有"很好"的信用,意味著借方的信用得分要高于700。

          貸款申請(qǐng)使用案例

            信用請(qǐng)求處理使用案例包括以下幾個(gè)步驟:

          1. 用戶在貸款申請(qǐng)頁面輸入貸款詳情并提交貸款申請(qǐng)。
          2. 發(fā)送請(qǐng)求到一個(gè)名為CreditRequestSendQueue的消息隊(duì)列。然后程序發(fā)送貸款詳情到AUS系統(tǒng),獲取信用歷史詳情。
          3. AUS系統(tǒng)從隊(duì)列中挑出貸款詳情,并使用貸款參數(shù)從它的數(shù)據(jù)庫(kù)中獲取信用歷史信息。
          4. 然后AUS將找到的借方的信用歷史信息創(chuàng)建一個(gè)新的消息,發(fā)送到一個(gè)新的名為CreditRequestReceiveQueue的消息隊(duì)列。
          5. 最后,LoanProc從接收隊(duì)列中選出響應(yīng)消息,處理貸款申請(qǐng)來決定是否批準(zhǔn)或否決申請(qǐng)。

            在這個(gè)例程中,兩個(gè)消息隊(duì)列都配置在同一個(gè)JBoss MQ server上。使用案例用圖1的序列圖(SequenceDiagram)表示

          序列圖

          圖1.貸款處理程序的序列圖 (單擊截圖來查看完整視圖)

             下面的表3顯示了在例程中我所使用的不同技術(shù)和開源框架,并按應(yīng)用邏輯層排列。

             表3. 在JMS應(yīng)用程序中使用的框架

          邏輯層技術(shù)/框架
          MVCSpring MVC
          ServiceSpring Framework (version 2.1)
          JMS APISpring JMS
          JMS ProviderJBoss MQ (version 4.0.2)
          JMS ConsoleHermes
          IDEEclipse 3.1

          使用Hermes設(shè)置JMS資源

            為了異步處理消息,首先我們需要消息隊(duì)列發(fā)送和接收消息。我們可以用Jboss里的配置XML文件創(chuàng)建一個(gè)新的消息隊(duì)列,然后使用JMS控制臺(tái)瀏覽隊(duì)列的詳細(xì)情況。清單1顯示了配置JMS的XML配置代碼片斷(這個(gè)應(yīng)該加入到j(luò)bossmq-destinations-service.xml文件,位于%JBOSS_HOME%\server\all\deploy-hasingleton\jm文件夾下。)

             清單1.JBoss MQ Server上JMS隊(duì)列的配置

          <!--  Credit Request Send Queue  -->
          <mbean code="org.jboss.mq.server.jmx.Queue"
            name="jboss.mq.destination:service=Queue,name=CreditRequestSendQueue">
            <depends optional-attribute-name="DestinationManager">
           jboss.mq:service=DestinationManager
            </depends>
          </mbean>
          
          <!--  Credit Request Receive Queue  -->
          <mbean code="org.jboss.mq.server.jmx.Queue"
            name="jboss.mq.destination:service=Queue,name=CreditRequestReceiveQueue">
            <depends optional-attribute-name="DestinationManager">
           jboss.mq:service=DestinationManager
            </depends>
          </mbean>
          

            現(xiàn)在,讓我們看看如何使用一個(gè)名為Hermes的JMS工具來瀏覽消息隊(duì)列。Hermes是一個(gè)Java Swing應(yīng)用程序,它可以創(chuàng)建、管理和監(jiān)視JMS提供商(例如JBossMQWebSphereMQActiveMQArjuna服務(wù)器)里的JMS目標(biāo)。從它的網(wǎng)站上下載Hermes,解壓縮.zip文件到本地目錄(例如,c:\dev\tools\hermes)。一旦安裝完成,雙擊文件hermes.bat(位于bin文件夾下)啟動(dòng)程序。

             要在Hermes里配置JBossMQ服務(wù)器,請(qǐng)參考Hermes網(wǎng)站上的這個(gè)演示。它有著出色的step-by-step可視化指示來配置JBoss MQ。當(dāng)配置一個(gè)新的JNDI初始上下文時(shí),請(qǐng)輸入下面的信息。

          • providerURL = jnp://localhost:1099
          • initialContextFactory = org.jnp.interfaces.NamingContextFactory
          • urlPkgPrefixes = org.jnp.interfaces:org.jboss.naming
          • securityCredentials = admin
          • securityPrincipal = admin

            當(dāng)您創(chuàng)建新的目標(biāo)時(shí),請(qǐng)輸入queue/CreditRequestSendQueue和queue/CreditRequestReceiveQueue。圖2顯示了JMS控制臺(tái)的主窗口,其中有為JMS例程創(chuàng)建的新的消息隊(duì)列。

          Hermes中所有目標(biāo)的截圖

          圖 2. Hermes中所有目標(biāo)的截圖.(單擊截圖來查看完整視圖)

             下面的圖3顯示了在從消息發(fā)送者類發(fā)送消息到CreditRequestSendQueue后,Hermes JMS控制臺(tái)及消息隊(duì)列的截圖。您可以看見有5個(gè)消息在隊(duì)列中,控制臺(tái)顯示了消息詳情,例如消息ID,消息目標(biāo),時(shí)間戳和實(shí)際的消息內(nèi)容。

          Hermes中所有隊(duì)列的截圖

          圖 3. Hermes中所有隊(duì)列的截圖.(單擊截圖來查看完整視圖)

             在例程中使用的隊(duì)列名稱和其他JMS和JNDI參數(shù)見表 4。

             表4. Spring JMS配置參數(shù)

          參數(shù)名稱參數(shù)值
          Initial Context Factoryorg.jnp.interfaces.NamingContextFactory
          Provider URLlocalhost:8080
          Initial Context Factory URL Packagesorg.jnp.interfaces:org.jboss.naming
          Queue Connection FactoryUIL2ConnectionFactory
          Queue Namequeue/CreditRequestSendQueue, queue/CreditRequestReceiveQueue

          Spring配置

            既然我們已經(jīng)有了運(yùn)行例程所需要的JMS目標(biāo),現(xiàn)在該了解用XML Spring配置文件(名為spring-jms.xml)來組配JMS組件的具體細(xì)節(jié)了。這些組件是根據(jù)Inversion of Controller (IOC)設(shè)計(jì)模式里的設(shè)置方式注入原則(setter injection principle),用JMS對(duì)象實(shí)例類組配的。讓我們?cè)敿?xì)查看這些組件,并為每一個(gè)JMS組件演示一段XML配置代碼。

             JNDI上下文是取得JMS資源的起始位置,因此首先我們要配置JNDI模板。清單2顯示了名為jndiTemplate的Spring bean,其中列有JNDI初始上下文所必需的常用參數(shù)。

             清單2. JNDI上下文模板

          <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
              <property name="environment">
                  <props>
                      <prop key="java.naming.factory.initial">
                          org.jnp.interfaces.NamingContextFactory
                      </prop>
                      <prop key="java.naming.provider.url">
                          localhost
                      </prop>
                      <prop key="java.naming.factory.url.pkgs">
                          org.jnp.interfaces:org.jboss.naming
                      </prop>
                  </props>
              </property>
          </bean>
          

            接著,我們配置隊(duì)列連接工廠。清單3顯示了隊(duì)列連接工廠的配置。

             清單3. JMS隊(duì)列連接工廠配置

          <bean id="jmsQueueConnectionFactory"
                class="org.springframework.jndi.JndiObjectFactoryBean">
              <property name="jndiTemplate">
                  <ref bean="jndiTemplate"/>
              </property>
              <property name="jndiName">
                  <value>UIL2ConnectionFactory</value>
              </property>
          </bean>
          

            我們定義2個(gè)JMS目標(biāo)來發(fā)送和接收消息。詳情見清單4和5。

             清單4. 發(fā)送隊(duì)列配置

          <bean id="sendDestination"
              class="org.springframework.jndi.JndiObjectFactoryBean">
              <property name="jndiTemplate">
                  <ref bean="jndiTemplate"/>
              </property>
              <property name="jndiName">
                  <value>queue/CreditRequestSendQueue</value>
              </property>
          </bean>
          

            清單5. 接收隊(duì)列配置

          <bean id="receiveDestination"
              class="org.springframework.jndi.JndiObjectFactoryBean">
              <property name="jndiTemplate">
                  <ref bean="jndiTemplate"/>
              </property>
              <property name="jndiName">
                  <value>queue/CreditReqeustReceiveQueue</value>
              </property>
          </bean>
          

            然后我們?cè)賮砼渲肑msTemplate組件。在例程中我們使用JmsTemplate102。同時(shí)使用defaultDestination屬性來指定JMS目標(biāo)。

             清單6. JMS模板配置

          <bean id="jmsTemplate" 
                class="org.springframework.jms.core.JmsTemplate102">
              <property name="connectionFactory">
                  <ref bean="jmsQueueConnectionFactory"/>
              </property>
              <property name="defaultDestination">
                  <ref bean="destination"/>
              </property>
              <property name="receiveTimeout">
                  <value>30000</value>
              </property>
          </bean>
          

            最后我們配置發(fā)送者和接收者組件。清單7和8分別是Sender 和 Receiver對(duì)象的配置。

             清單7. JMS Sender配置

          <bean id="jmsSender" class="springexample.client.JMSSender">
              <property name="jmsTemplate">
                  <ref bean="jmsTemplate"/>
              </property>
          </bean>
          

            清單8. JMS Receiver配置

          <bean id="jmsReceiver" class="springexample.client.JMSReceiver">
              <property name="jmsTemplate">
                  <ref bean="jmsTemplate"/>
              </property>
          </bean>
          

          測(cè)試及監(jiān)視

            我寫了一個(gè)測(cè)試類,命名為L(zhǎng)oanApplicationControllerTest,用來測(cè)試LoanProc程序。我們可以使用這個(gè)類來設(shè)定貸款參數(shù)以及調(diào)用信用請(qǐng)求服務(wù)類。

             讓我們看一下不使用Spring JMS API而使用傳統(tǒng)JMS開發(fā)途徑的消息發(fā)送者實(shí)例。清單9顯示了MessageSenderJMS類里的sendMessage方法,其中包含了使用JMS API處理消息的所有必需步驟。

             清單9. 傳統(tǒng)JMS實(shí)例

          public void sendMessage() {
          
              queueName = "queue/CreditRequestSendQueue";
              System.out.println("Queue name is " + queueName);
          
              /*
               * Create JNDI Initial Context
               */
              try {
                  Hashtable env = new Hashtable();
                  env.put("java.naming.factory.initial",
                      "org.jnp.interfaces.NamingContextFactory");
                  env.put("java.naming.provider.url","localhost");
                  env.put("java.naming.factory.url.pkgs",
                      "org.jnp.interfaces:org.jboss.naming");
          
                  jndiContext = new InitialContext(env);
              } catch (NamingException e) {
                  System.out.println("Could not create JNDI API " +
                      "context: " + e.toString());
              }
          
              /*
               * Get queue connection factory and queue objects from JNDI context.
               */
              try {
                  queueConnectionFactory = (QueueConnectionFactory)
                  jndiContext.lookup("UIL2ConnectionFactory");
          
                  queue = (Queue) jndiContext.lookup(queueName);
              } catch (NamingException e) {
                  System.out.println("JNDI API lookup failed: " +
                      e.toString());
              }
          
              /*
               * Create connection, session, sender objects.
               * Send the message.
               * Cleanup JMS connection.
               */
              try {
                  queueConnection =
                      queueConnectionFactory.createQueueConnection();
                  queueSession = queueConnection.createQueueSession(false,
                          Session.AUTO_ACKNOWLEDGE);
                  queueSender = queueSession.createSender(queue);
                  message = queueSession.createTextMessage();
                  message.setText("This is a sample JMS message.");
                  System.out.println("Sending message: " + message.getText());
                  queueSender.send(message);
          
              } catch (JMSException e) {
                  System.out.println("Exception occurred: " + e.toString());
              } finally {
                  if (queueConnection != null) {
                      try {
                          queueConnection.close();
                      } catch (JMSException e) {}
                  }
              }
          }
          

            現(xiàn)在,我們來看看使用了Spring的消息發(fā)送者實(shí)例。清單10顯示了MessageSenderSpringJMS類中send方法的代碼。

             清單10. 使用Spring API的JMS實(shí)例

          public void send() {
              try {
                  ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] {
                          "spring-jms.xml"});
          
                  System.out.println("Classpath loaded");
          
                  JMSSender jmsSender = (JMSSender)appContext.getBean("jmsSender");
          
                  jmsSender.sendMesage();
          
                  System.out.println("Message sent using Spring JMS.");
              } catch(Exception e) {
                  e.printStackTrace();
              }
          }
          

            如您所見,通過使用配置文件,所有與管理JMS資源有關(guān)的步驟都將交由Spring容器處理。我們只需引用一個(gè)JMSSender對(duì)象,然后調(diào)用對(duì)象里的sendMessage方法。

          結(jié)束語

            在本文中,我們看到Spring框架是如何使用JMS API簡(jiǎn)化異步消息傳遞。Spring去掉了所有使用JMS處理消息所必需的樣本代碼(例如得到一個(gè)隊(duì)列連接工廠,從Java代碼里創(chuàng)建隊(duì)列和會(huì)話對(duì)象,在運(yùn)行時(shí)使用配置文件對(duì)它們進(jìn)行組配)。我們可以動(dòng)態(tài)的交換JMS資源對(duì)象,而不必修改任何Java代碼,這要感謝Inversion of Control (IOC) 原則的力量。

            既然異步消息傳遞是SOA框架的整體構(gòu)成部分,Spring很適合納入到SOA工具集。此外,JMS管理工具(如Hermes)使得創(chuàng)建、管理和監(jiān)督JMS資源變得容易,特別是對(duì)于系統(tǒng)管理員來說。

          主站蜘蛛池模板: 淮安市| 阆中市| 霍州市| 四子王旗| 揭西县| 黄大仙区| 延安市| 德庆县| 无为县| 冷水江市| 锡林郭勒盟| 堆龙德庆县| 禹州市| 明水县| 亚东县| 秦皇岛市| 北碚区| 墨竹工卡县| 洪泽县| 金川县| 新和县| 和田市| 阜康市| 五台县| 务川| 左云县| 柳林县| 东乡| 宽甸| 富民县| 衡南县| 桦川县| 稷山县| 洛南县| 广州市| 天气| 重庆市| 怀远县| 固原市| 溧水县| 乡城县|