<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Cyh的博客

    Email:kissyan4916@163.com
    posts - 26, comments - 19, trackbacks - 0, articles - 220

    筆記之Spring-JMS

    Posted on 2009-03-11 00:31 啥都寫點(diǎn) 閱讀(3260) 評(píng)論(0)  編輯  收藏 所屬分類: J2EE


     

    JMS簡(jiǎn)介:一種應(yīng)用于異步消息傳遞的標(biāo)準(zhǔn)API,JMS也是應(yīng)用于程序間通訊的。但是,JMS與其他機(jī)制有所不同,主要表現(xiàn)在系統(tǒng)間傳遞信息的方式,見(jiàn)PPT1-2。簡(jiǎn)介傳送也是JMS的關(guān)鍵。當(dāng)一個(gè)應(yīng)用程序通過(guò)JMS向另一個(gè)應(yīng)用程序發(fā)送消息時(shí),兩個(gè)程序之間并沒(méi)有直接的連接。發(fā)送應(yīng)用程序會(huì)將消息交給一個(gè)服務(wù),由服務(wù)確保將消息投遞給接收應(yīng)用程序。在JMS中有兩個(gè)主要的概念:消息中介(message broker)和消息目標(biāo)(destination)。當(dāng)應(yīng)用程序發(fā)送消息時(shí),會(huì)將消息交給一個(gè)消息中介。消息中介實(shí)際上就是JMS版本的郵局。消息中介可以確保消息被投遞到指定的消息目標(biāo),同時(shí)可以釋放發(fā)送者,使其能夠進(jìn)行其他的業(yè)務(wù)。 在JMS中,每條消息帶有一個(gè)消息目標(biāo)。消息目標(biāo)就好像一個(gè)郵箱,可以將消息放入這個(gè)郵箱,直到有人將它們?nèi)〕觥O⒛繕?biāo)只關(guān)心消息應(yīng)該從哪里獲得--而不是由誰(shuí)來(lái)獲得。在JMS中,有兩種消息目標(biāo)類型:隊(duì)列和主題。分別應(yīng)用于隊(duì)列的點(diǎn)對(duì)點(diǎn)模型或應(yīng)用于主題的發(fā)布--訂閱模型。

    • 點(diǎn)對(duì)點(diǎn)消息傳遞模型:在點(diǎn)對(duì)點(diǎn)模型中,每個(gè)消息都有一個(gè)發(fā)送者和一個(gè)接收者,見(jiàn)PPT3.在JMS中如果有多個(gè)接收者監(jiān)聽隊(duì)列,就沒(méi)辦法直到某條特定的消息會(huì)被哪個(gè)接收者處理。這種不確定性實(shí)際上有很多好處,因?yàn)樗梢宰尦绦蛑脼殛?duì)列添加監(jiān)聽器就能增大消息處理的能力。

      發(fā)布--訂閱消息傳遞模型:在此模型中,消息會(huì)被發(fā)送給一個(gè)主題。像使用隊(duì)列一樣,可以讓多個(gè)接收者監(jiān)聽一個(gè)主題。但是,與隊(duì)列不同的是消息不再被只投遞給一個(gè)接收者,所有主題的訂閱者都會(huì)收到消息,見(jiàn)PPT4。

    JMS的優(yōu)點(diǎn)不用等待--當(dāng)使用JMS發(fā)送消息時(shí),客戶端不必等待消息被處理,甚至是被投遞。客戶端只需要將消息發(fā)給消息中介,就可以確信消息會(huì)被投遞到適當(dāng)?shù)哪繕?biāo)。因?yàn)椴槐氐却蛻舳司涂梢詧?zhí)行其他的任務(wù)。由于這種方法可以大大地節(jié)省時(shí)間,客戶端的性能能夠極大地提高。面向消息--與RFC通信面向方法調(diào)用不同,使用JMS發(fā)送消息是以數(shù)據(jù)位中心的。這意味著客戶端不用固定搭配特定的方法符號(hào)。任何隊(duì)列或主題訂閱者都可以處理由客戶端發(fā)送來(lái)的消息。客戶端不必了解服務(wù)的任何規(guī)范。位置獨(dú)立--JMS客戶端不必知道由誰(shuí)來(lái)處理他們的消息,或者服務(wù)的位置在哪里。客戶端值需要了解需要通過(guò)哪個(gè)隊(duì)列或主題發(fā)送消息。因此,只要能夠從隊(duì)列或主題獲取消息,JMS客戶端就不用在意服務(wù)的位置在哪里。確保投送--當(dāng)使用JMS發(fā)送消息時(shí),客戶端能夠確保消息被投遞。即使在消息發(fā)送時(shí)服務(wù)無(wú)法使用,消息也會(huì)被儲(chǔ)存起來(lái),直到服務(wù)重新可以使用為止。

    在Spring中安裝ActiveMQ:它是一個(gè)開源消息中介(Apache的一個(gè)子項(xiàng)目),也是應(yīng)用JMS異步消息傳遞的很好選擇。需要從www.activemq.org下載包。在bin目錄中,可以找到一個(gè)用于啟動(dòng)ActiveMQ的腳本:Unix用戶的activemq或者Windows用戶的activemq.bat。運(yùn)行這個(gè)腳本,等ActiveMq啟動(dòng)后,就可以使用它進(jìn)行中介服務(wù)了。在所有的示例中,都需要通過(guò)JMS連接工廠通過(guò)消息中介發(fā)送消息。我們選擇了ActiveMQ作為消息中介,因此必須配置JMS連接工廠,使它能夠了解如何連接到ActiveMQ,ActiveMQConnectionFactory是連接ActiveMQ的JMS連接工廠,在Spring中配置如下:

    <bean id ="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory" >

           <property  name="brokerURL" value="tcp://localhost:61616">

    </bean>

    • 聲明一個(gè)ActiveMQ隊(duì)列: 

        <bean id="rantzDestination" class="org.apache.activemq.command.ActiveMQQueue">

              <constructor-arg index="0" value="rantz.marketing.queue" />

       </bean>

      聲明一個(gè)ActiveMQ主題

        <bean id="rantzDestination" class="org.apache.activemq.command.ActiveMQTopic">

              <constructor-arg index="0" value="rantz.marketing.topic" />

       </bean>

    協(xié)同使用JMS和Spring:JMS為Java愛(ài)好者提供了一個(gè)與消息中介進(jìn)行交互,以及發(fā)送和接收消息的標(biāo)準(zhǔn)API,而且每一個(gè)消息中介的實(shí)現(xiàn)都會(huì)支持JMS。因此你不必由于消息中介的不同而學(xué)習(xí)不同的消息傳遞的API。雖然JMS為所有的消息中介提供了統(tǒng)一接口,但這種接口用起來(lái)不是十分便利(見(jiàn)PPT5-6)

    • 使用JMS模板:JmsTemplate是Spring消除冗長(zhǎng)和重復(fù)JMS代碼的解決方案。JmsTemplate可以創(chuàng)建連接,獲取會(huì)話,以及發(fā)送和接收消息。它使你可以專注于構(gòu)建要發(fā)送的消息或者處理收到的消息。另外,JmsTemplate可以處理任何被拋出的JMSException。如果JMSException在JmsTemplate工作中被拋出,JmsTemplate將捕獲這個(gè)異常,并且用一個(gè)未受查的JmsException的子類再次拋出它。見(jiàn)PPT7

      置入JmsTemplate模板

      <bean id ="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">

         <property name="connectionFactory" ref="connectionFactory">

      </bean>

      • 發(fā)送消息:在RoadRantz端,我們使用JmsTemplate向RoandRantz市場(chǎng)發(fā)送駕駛員信息。RantzMarketingGatewayImpl是RoadRantz與市場(chǎng)系統(tǒng)進(jìn)行交互的類。見(jiàn)PPT8,因此,當(dāng)我們?cè)赟pring中配置RantzMarKetingGatewayImpl類時(shí),必須置入jmsTemplate和rantzDestination Bean的參考:

          <bean id="marketingGateway"  class="com.roadrantz.marketing.RantzMarketingGatewayImpl">

                <property name="jmsTemplate" ref ="jmsTemplate"  />

                <property name="destination" ref="rantzDestination"  />

         </bean>

        設(shè)置默認(rèn)目標(biāo):如果每次發(fā)送消息都指定一個(gè)目標(biāo),不如為JmsTemplate置入一個(gè)默認(rèn)目標(biāo):

        <bean id ="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">

           <property name="connectionFactory" ref="connectionFactory" />

          <property name="defaultDestination" ref="rantzDestination" />

        </bean>

        現(xiàn)在,調(diào)用JmsTemplate的send()方法就可以去掉第一個(gè)參數(shù)了。這種send()方法的形式只帶有一個(gè)MessageCreator。因?yàn)闆](méi)有指定目標(biāo),JmsTemplate會(huì)假設(shè)你要將消息發(fā)送給默認(rèn)目標(biāo)。所以不必再為RantzMarketingGatewayImpl注入目標(biāo)了。它的聲明很簡(jiǎn)單:

          <bean id="marketingGateway"  class="com.roadrantz.marketing.RantzMarketingGatewayImpl">

                <property name="jmsTemplate" ref ="jmsTemplate"  />

         </bean>

        消費(fèi)消息:使用JmsTemplate接收消息十分簡(jiǎn)單。只需要調(diào)用JmsTemplate的receive()方法,如PPT9. 默認(rèn)情況下,對(duì)receive()方法的調(diào)用會(huì)造成阻塞,直到消息到達(dá)目標(biāo)--如果必要,會(huì)永遠(yuǎn)等待下去。為了避免對(duì)消息的內(nèi)部等待,可以通過(guò)配置JmsTemplate時(shí),通過(guò)設(shè)置receiveTimeout屬性來(lái)指定接收時(shí)間。下面配置的接收超時(shí)時(shí)間為一分鐘(60000毫秒)。

        <bean id ="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">

           <property name="connectionFactory" ref="connectionFactory" />

          <property name="defaultDestination" ref="rantzDestination" />

          <property name="receiveTimeout" value="60000" />

        </bean>

        在PPT9中,receive()方法會(huì)從默認(rèn)目標(biāo)接收消息。如果你希望指定一個(gè)目標(biāo),可以為其傳遞一個(gè)目標(biāo):

        MapMessage message = (MapMessage) jmsTemplate.receive(destination);

        此外,還可以通過(guò)名稱指定目標(biāo),并且讓Spring的目標(biāo)解析器自動(dòng)解析這個(gè)目標(biāo):

         MapMessage message = (MapMessage) jmsTemplate.receive("rantz.marketing.queue");

        轉(zhuǎn)換消息:為了簡(jiǎn)化示例,沒(méi)有在發(fā)送和接收消息的代碼中添加處理消息轉(zhuǎn)換的代碼。但是,如果在程序中的多個(gè)位置都需要發(fā)送或接收相同的消息,可能就需要通過(guò)消息轉(zhuǎn)換器來(lái)避免不必要的映射代碼。盡管將消息轉(zhuǎn)換代碼抽象成自己的工具類并不是很困難,但是你仍然需要明確的調(diào)用工具類來(lái)進(jìn)行轉(zhuǎn)換。幸運(yùn)的是,Spring通過(guò)MessageConverter接口提供了對(duì)消息轉(zhuǎn)換的支持:

            public interface MessageConverter {

                public Message toMessage(Object  object, Session session);

                public Object fromMessage (Message message) ;

         } 

           見(jiàn)PPT10,展示了一個(gè)MessageConverter接口的實(shí)現(xiàn)MotoristMessageConverter,可以將Motorist對(duì)象轉(zhuǎn)換為消息,也可以將消息轉(zhuǎn)換為SpammedMotorist對(duì)象。

        • 發(fā)送和接收被轉(zhuǎn)換的消息:我們可以在發(fā)送消息前不用明確的調(diào)用toMessage()方法,只需要調(diào)用JmsTemplate的convertAndSend()方法。因此,PPT8中的sendMotoristInfo()方法將變得更加簡(jiǎn)單:

                 public void sendMotoristInfo (final Motorist motorist){
                     jmsTemplate.converAndSend(motorist);  }      消息被發(fā)向JmsTemplate的默認(rèn)目標(biāo)(假設(shè)已經(jīng)指定了一個(gè)默認(rèn)目標(biāo))。不過(guò)我們也可以在調(diào)用convertAndSend()方法時(shí)指定一個(gè)特定的目標(biāo):             jmsTemplate.connverAndSend(destination,motorist);  另外,我們也可以通過(guò)名稱指定目標(biāo):                     jmsTemplate.convertAndSend("rantz.marketing.queue",motorist);  接收端:         public SpammedMotorist receiveSpammedMotorist() {    return (SpammedMotorist) jmsTemplate.receiveAndConvert();        }   除非有特殊的指定,recieveAndConvert()會(huì)從默認(rèn)目標(biāo)接收消息。不過(guò),我們也可以通過(guò)為receiveAndConvert()方法傳遞一個(gè)參數(shù)來(lái)選擇一個(gè)目標(biāo):          return (SpammedMotorist) jmsTemplate.receiveAndConvert(destination);    或者使用目標(biāo)的名稱: return (SpammedMotorist) jmsTemplate.receiveAndConvert("rantz.marketing.queue");

          置入消息轉(zhuǎn)化器:  <bean id="motoristConverter" class="com.roadrantz.marketing.MotoristMessageConverter" />

          最后,JmsTemplate需要了解這個(gè)消息轉(zhuǎn)換器。為了提供消息轉(zhuǎn)換器,我們會(huì)將motoristConverter Bean置入到JmsTemplate的messageConverter屬性中:

          <bean id ="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">

             <property name="connectionFactory" ref="connectionFactory" />

            <property name="defaultDestination" ref="rantzDestination" />

            <property name="messageConverter" ref="motoristConverter" />

          </bean>

      將Spring的網(wǎng)關(guān)支持類應(yīng)用于JMS: Spring通過(guò)提供JdbcDaoSupport使JdbcTemplate的應(yīng)用比原先變得更簡(jiǎn)單一些。與此類似,Spring也提供了一個(gè)用于JMS網(wǎng)關(guān)類的基類JmsGatewaySupport(見(jiàn)PPT11)。 那么JmsGatewaySupport從哪里得到JmsTemplate呢?你可以直接在jmsTemplate屬性中注入JmsTemplate,就像處理常規(guī)的RantzMarketingGatewayImpl一樣。或者,可以為connectionFactory屬性置入連接工廠,來(lái)滿足對(duì)JmsTemplate Bean的所有需求:

       <bean id = "marketingGateway" class="com.roadrantz.marketing.RantzMarketingGatewayImple">

          <property name="connectionFactory " ref="connectionFactory" />

      </bean>

        當(dāng)這種方法配置時(shí),JmsGateSupport將基于被注入的連接工廠自動(dòng)創(chuàng)建一個(gè)JmsTemplate對(duì)象。因此不必在Spring中聲明JmsTemplate Bean。 在直接將連接工廠置入到網(wǎng)關(guān)之前,你應(yīng)該了解這種方法有兩個(gè)缺點(diǎn)

      1、只能在JmsTemplate上指定默認(rèn)目標(biāo)。如果JmsGateSupport創(chuàng)建了自己的JmsTemplate,就沒(méi)有機(jī)會(huì)再指定默認(rèn)的目標(biāo)了。你必須在調(diào)用send()或receive()時(shí)明確地選擇一個(gè)目標(biāo)。

      2、只能將消息轉(zhuǎn)換器置入到JmsTemplate中。如果JmsGatewaySupport創(chuàng)建了自己JmsTemplate,將不能使用消息轉(zhuǎn)換器。因此,必須明確地在網(wǎng)關(guān)代碼中處理消息的轉(zhuǎn)換。

    創(chuàng)建消息驅(qū)動(dòng)POJO:EJB2.0規(guī)范的其中一個(gè)重要內(nèi)容是包含了消息驅(qū)動(dòng)Bean(MDB)。MDB是可以異步處理消息的EJB。換句話說(shuō),MDB會(huì)將JMS目標(biāo)中的消息作為事件來(lái)響應(yīng)。這與同步消息接收者在消息可用前進(jìn)行阻塞正好相反。MDB是EJB的一個(gè)兩點(diǎn)。在EJB3的規(guī)范中,MDB被簡(jiǎn)化了,使其更像POJO。不再需要實(shí)現(xiàn)MessageDrivenBean接口,只需要實(shí)現(xiàn)常規(guī)的java.jms.MessageListener接口并用@MessageDriven注釋MDB。Spring2.0通過(guò)自己的消息驅(qū)動(dòng)Bean形式來(lái)滿足消息的異步消費(fèi)需求。

    • 創(chuàng)建消息監(jiān)聽器:MarketingMdp不必實(shí)現(xiàn)MessageDrivenBean接口的世界是多么簡(jiǎn)單,見(jiàn)PPT12。MarketingMdp本身并不做些什么。它有一個(gè)實(shí)際處理消息的onMessage()方法。不過(guò)要先在Spring中配置一下:

      <bean id="rantzMdp" class="com.roadrantz.marketing.MarketingMdp"  />

      EJB3.0MDB會(huì)使用@MessageDriven注釋通知容器這是一個(gè)MDB。但是,在Spring中,我們會(huì)通過(guò)將其注入到一個(gè)消息監(jiān)聽容器來(lái)指示這個(gè)Bean是一個(gè)MDP。

      包含消息監(jiān)聽器:消息監(jiān)聽器容器是一個(gè)用于查看JMS目標(biāo),等待消息到達(dá)的特殊Bean。一旦消息到達(dá),它就可以獲取到消息,并通過(guò)onMessage()方法將消息傳遞給一個(gè)MessageListener的實(shí)現(xiàn)。因?yàn)镸arketingMdp類實(shí)現(xiàn)了MessageListener接口,所以消息監(jiān)聽器容器就準(zhǔn)備完畢了。見(jiàn)PPT13. 顧名思義,SimpleMessageListenerContainer是最簡(jiǎn)單的消息監(jiān)聽器容器,可以按下面的方法在Spring中進(jìn)行配置:

      <bean class="org.springframework.jms.listener.SimpleMessageListenerContainer">

           <property name="connectionFactory" ref="connectionFactory" />

           <property name="destination" ref="rantzDestination" />

           <property name="messageListener" ref="rantzMdp" />

      </bean> 

      對(duì)于messageListener屬性,我們?yōu)槠渲萌肓藢?duì)MDP實(shí)現(xiàn)的引用,這樣,onMessage()方法將可以被用來(lái)接收消息。

      使用事務(wù)性的MDP:如果收到的一個(gè)消息在事務(wù)中,則應(yīng)該使用DefaultMessageListenerContainer:

       <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">

           <property name="connectionFactory" ref="connectionFactory" />

           <property name="destination" ref="rantzDestination" />

           <property name="messageListener" ref="rantzMdp" />

           <property name="transactionManager" ref="jmsTransactionManager" />

      </bean>  如果事務(wù)性需求比較簡(jiǎn)單,JmsTransactionManager將按如下方法配置:

       <bean id="jmsTransactionManager" class="org.springframework.jms.connection.JmsTransactionManager">

           <property name="connectionFactory" ref="connectionFactory" />

      </bean>  需要提醒的是,tansactionManger屬性是可選的。如果不注入事務(wù)管理器,MDP就不是事務(wù)性的。

      編寫純POJO MDP:如果消息監(jiān)聽器容器的messageListener屬性被注入了MessageListener的實(shí)現(xiàn),它就能夠知道在消息到達(dá)時(shí)應(yīng)該調(diào)用onMessage()方法。幸運(yùn)的是,Spring提供了一個(gè)替代的MessageListenerAdapter。它是一個(gè)MessageListener,可以委派Bean和你選擇的方法,見(jiàn)PPT14. 如果不將自己的MessageListener的實(shí)現(xiàn)注入到消息監(jiān)聽器容器中,你可以置入到MessageListenerAdapter中:

      <bean class="org.springframework.jms.listener.SimpleMessageListenerContainer">

           <property name="connectionFactory" ref="connectionFactory" />

           <property name="destination" ref="rantzDestination" />

           <property name="messageListener" ref ="purePojoMdp" />

      </bean> 因?yàn)榕渲昧藀urePojoMdp Bean,所以它是一個(gè)MessageListenerAdapter:

       <bean id="purePojoMdp" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">

          <property name="delegate" ref="rantzMdp" />

          <property name="defaultListenerMethod"  value="processMotoristInfo" />

      </bean> 默認(rèn)情況下,MessageListenerAdapter在消息到達(dá)時(shí)會(huì)調(diào)用handleMessage()方法。但是,我們希望MarketingMdp Bean可以通過(guò) processMotoristInfo()方法處理消息,因此將defaultListenerMethod設(shè)置為processMotoristInfo.    因?yàn)檫x擇了一個(gè)特定的被調(diào)用方法,所以不需要實(shí)現(xiàn)MessageListener或onMessage()方法。因此 MarketingMdp現(xiàn)在將被簡(jiǎn)化為PPT15。盡管它是一個(gè)POJO,對(duì)MapMessage的依賴造成了MarketingMdp與JMS的不必要耦合,另外,MapMessage的getString方法還會(huì)拋出必須被處理的JMSException。理想情況下,MarketingMdp不應(yīng)該依賴任何特定框架的類型。 當(dāng)MessageListenerAdapter接收消息時(shí),它會(huì)考慮消息的類型和defaultListenerMethod的值,并且嘗試著查找用來(lái)調(diào)用的監(jiān)聽器方法符號(hào)。PPT16描述了MessageListenerAdapter是如何將JMS消息映射到監(jiān)聽器方法參數(shù)的。

      轉(zhuǎn)換MDP消息:在最新版中,processMotoristInfo()帶有的是Map,并且在處理前需要將Map轉(zhuǎn)換為SpammedMotorist。如果在消息到達(dá)時(shí),能夠直接給processMotoristInfo()方法傳遞可以處理的SpammedMotorist對(duì)象豈不是更好么?Spring消息轉(zhuǎn)換器可以執(zhí)行消息和特定域Java類型之間的相互轉(zhuǎn)換工作。在PPT10中,已經(jīng)有一個(gè)消息轉(zhuǎn)換器。我們需要做的就是讓MessageListenerAdapter能夠感知這個(gè)消息轉(zhuǎn)換器。MessageListenerAdapter的messageConverter屬性可以完成這項(xiàng)工作:

      <bean id="purePojoMdp" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">

          <property name="delegate" ref="rantzMdp" />

          <property name="defaultListenerMethod"  value="processMotoristInfo" />

          <propert name="messageConverter" ref="motoristConverter" />

      </bean> 現(xiàn)在,可以編寫最終版的MarketingMdp了。

    使用基于消息的RPC:RPC編程模型可以使與遠(yuǎn)程服務(wù)的交互就如同在調(diào)用本地對(duì)象的方法。是否有某種方法既具有RPC編程模型的簡(jiǎn)單性,又可以利用異步消息傳遞的優(yōu)點(diǎn)呢?

    • 引入Lingo: 它是一種基于Spring的遠(yuǎn)程調(diào)用方法,它在RPC和異步消息傳遞之間架起了一座橋梁。與使用其他的Spring遠(yuǎn)程調(diào)用方法相同,Lingo提供了一個(gè)服務(wù)輸出器,可以將Bean的功能輸出為L(zhǎng)ingo服務(wù)和客戶端代理。 Lingo遠(yuǎn)程調(diào)用會(huì)通過(guò)JMS隊(duì)列或主題來(lái)承載信息。 盡管Lingo是基于Spring遠(yuǎn)程調(diào)用的,但是它并不是Spring框架的一部分。你可以從Lingo的主頁(yè)下載Lingo(http://lingo.codehaus.org/Download).

      輸出服務(wù):在服務(wù)端,Lingo提供了一個(gè)服務(wù)輸出器JmsServiceExporter。被Lingo輸出的服務(wù)是通過(guò)JMS來(lái)提供服務(wù)的,而不是用于直接的RPC訪問(wèn),見(jiàn)PPT17。下面的XML配置了一個(gè)JmsServiceExporter,能夠?qū)antzMdp Bean輸出為RPC-over-JMS服務(wù):

      <bean id="server" class="org.logicblaze.lingo.jms.JmsServiceExporter">

           <property name="connectionFactory" ref="connectionFactory" />

           <property name="destination" ref="destination" />

           <property  name="service" ref="rantzMdp" />

           <property name="serviceInterface" value="com.roadrantz.marketing.MarketingService"  />

      </bean>

        service屬性被置入了對(duì)rantzMdp Bean的引用,即MarketingMdp。最后,應(yīng)該將定義了服務(wù)的接口的類名配置到serviceInterface屬性中。我們聲明的被輸出服務(wù)帶有MarketingService接口,定義如下:

        public interface MarketingService {

          void processMotoristInfo (SpammedMotorist motorist );

      }    因?yàn)槲覀兌x的服務(wù)帶有MarketingService接口,這就意味著我們應(yīng)該對(duì)MarketingMdp類進(jìn)行一些小的修改,以便它可以實(shí)現(xiàn)MarketingService接口:

        public class MarketingMdp implements MarketingService {

           public void processMotoristInfo(SpammedMotorist motorist) {

               ...

          }

      }

      這就是使用Lingo輸出服務(wù)的全過(guò)程。一旦應(yīng)用程序啟動(dòng),JmsServiceExporter將會(huì)起作用,就可以開始使用它了。現(xiàn)在,讓我們?cè)俚娇蛻舳丝纯碦oadRantz應(yīng)用程序是如何調(diào)用這個(gè)被輸出的市場(chǎng)服務(wù)的。

      代理JMS:在RoadRantz應(yīng)用程序中,每次用戶注冊(cè)并選擇愿意接收特定提供商信息時(shí)都需要調(diào)用processMotoristInfo()方法,因此,我們必須以某種方法將Lingo輸出服務(wù)的引用置入到RoadRantz應(yīng)用程序中。

      • 置入JmsProxyFactoryBean:lingo提供了JmsProxyFactoryBean,這是一個(gè)代理工廠Bean,可以生成遠(yuǎn)程Lingo輸出服務(wù)的代理。如PPT18所示,通過(guò)JmsProxyFactoryBean代理的服務(wù)是通過(guò)JMS目標(biāo)(隊(duì)列或主題)訪問(wèn)的,而不是通過(guò)TCP/IP。下面聲明配置了一個(gè)JmsProxyFactoryBean:

        <bean id = "marketing" class="org.logicblaze.lingo.jms.JmsProxyFactoryBean">

             <property name="connectionFactory" ref="connectionFactory" />

             <property name="destination" ref="destination" />

             <property name="serviceInterface" value="com.roadrantz.marketing.MarketingService" />

        </bean> serviceInterface屬性指定了代理需要實(shí)現(xiàn)的Java接口。通過(guò)這個(gè)接口,RoadRantz可以調(diào)用processMotoristInfo()方法。 對(duì)于配置JmsProxyFactoryBean,最需要注意的事情是不用配置服務(wù)的位置信息。這是因?yàn)榉?wù)的位置并不重要,只需要知道服務(wù)在哪里接收"郵件"。事實(shí)上,我們還可以使用遠(yuǎn)程服務(wù)的多個(gè)實(shí)例。如果想建立一個(gè)高可靠性的市場(chǎng)服務(wù),可以啟動(dòng)兩個(gè)或多個(gè)實(shí)例,讓它們都監(jiān)聽相同的目標(biāo)。每一個(gè)實(shí)例都能夠處理一個(gè)請(qǐng)求。其間,客戶端并不知道有一個(gè)服務(wù)池在等待請(qǐng)求進(jìn)行響應(yīng)。

        進(jìn)行調(diào)用:在JmsProxyFactoryBean被置入后,就可以開始調(diào)用遠(yuǎn)程服務(wù)了。我們需要做的是將其置入到RantServiceImpl:

        <bean id ="rantService" class="com.roadrantz.service.RantServiceImpl">

           <property name="rantDao" ref="rantDao" />

           <property name="marketingService" ref="marketing" />

        </bean>  接著,我們可以使用它在addMotorist()方法中向市場(chǎng)服務(wù)發(fā)送SpammedMotorist對(duì)象。PPT19展示了為了調(diào)用遠(yuǎn)程市場(chǎng)服務(wù)對(duì)RantServiceImpl進(jìn)行的相關(guān)修改。 正如你看到的,調(diào)用Lingo輸出的服務(wù)與調(diào)用RMI服務(wù)、Web服務(wù)或在同一個(gè)進(jìn)程中調(diào)用其他Bean上的方法是相同的。PPT19中沒(méi)有任何關(guān)于JMS的內(nèi)容。唯一不同的地方在Spring的配置。通過(guò)這種方法,只需要簡(jiǎn)單的更改Spring的配置就能夠在JMS和其他通信機(jī)制直接進(jìn)行切換。



                                                                                                           --    學(xué)海無(wú)涯
            

    主站蜘蛛池模板: 亚洲一区二区三区乱码A| 色婷婷亚洲十月十月色天| 二个人看的www免费视频| 久久亚洲国产成人精品性色| 一二三四影视在线看片免费| 免费大片av手机看片高清| 亚洲AV成人一区二区三区AV| 久久天天躁狠狠躁夜夜免费观看| 牛牛在线精品观看免费正| 亚洲av福利无码无一区二区| 国产片AV片永久免费观看| yellow免费网站| 亚洲一本之道高清乱码| AV在线播放日韩亚洲欧| 91成人免费在线视频| 好男人资源在线WWW免费| 2020久久精品亚洲热综合一本| 亚洲午夜福利精品无码| 无码中文字幕av免费放| a级片免费在线播放| 亚洲成AV人影片在线观看| 亚洲韩国—中文字幕| 亚洲第一黄色网址| 韩国免费一级成人毛片| 97无码人妻福利免费公开在线视频| 亚洲午夜无码久久久久小说| 亚洲av网址在线观看| 亚洲无码高清在线观看| 夫妻免费无码V看片| 蜜桃成人无码区免费视频网站| 免费亚洲视频在线观看| 国产成人精品亚洲2020| 亚洲AV无码精品无码麻豆| 亚洲精品成人片在线观看| 18禁超污无遮挡无码免费网站国产| 野花香高清在线观看视频播放免费| 精品免费AV一区二区三区| 精品久久久久久亚洲精品| 亚洲午夜精品久久久久久人妖 | 亚洲福利视频一区二区| 永久免费毛片在线播放|