細心!用心!耐心!

          吾非文人,乃市井一俗人也,讀百卷書,跨江河千里,故申城一游; 一兩滴辛酸,三四年學(xué)業(yè),五六點粗墨,七八筆買賣,九十道人情。

          BlogJava 聯(lián)系 聚合 管理
            1 Posts :: 196 Stories :: 10 Comments :: 0 Trackbacks

          快速應(yīng)用JMS控件訪問JMS資源

           

          JMS定義了Java中訪問消息中間件的接口,是企業(yè)資源異步訪問的主要形式。JMS可以和EJB技術(shù)集成使用,也就是常說的消息驅(qū)動BEAN。

            因為訪問JMS和訪問Entity EJB和SessionEJB的調(diào)用方法有很大的差異,所以Beehive中提供了專門的JMS控件來完成JMS資源的訪問。

          創(chuàng)建JMS控件的典型步驟
            Beehive中提供的JMS控件無法直接用于訪問JMS資源,使用者必須繼承JMS控件來創(chuàng)建自己的訪問控件,設(shè)置相關(guān)的環(huán)境后才能完成JMS資源的訪問。一個繼承控件中只能對應(yīng)的訪問唯一一個消息隊列/主題,如果需要向多個消息隊列/主題發(fā)送消息,必須針對每個消息隊列/主題提供相應(yīng)的控件。

            你可以使用下面的步驟來創(chuàng)建自己的控件實現(xiàn)對JMS資源的訪問:

          創(chuàng)建新的Java接口,繼承JMSControl接口
          用@ControlExtension關(guān)鍵字注釋新創(chuàng)建的Java接口,通知解析器這個接口繼承了另外的某個控件。
          使用@JMSControl.Destination注釋新創(chuàng)建的Java接口,說明控件如何搜索消息隊列/主題,同時使用sendType聲明發(fā)送目標(biāo)是消息隊列還是消息主題。
          創(chuàng)建新的業(yè)務(wù)方法,使用JMSControl.Message注釋來聲明被發(fā)送消息的類型,或者使用不同的參數(shù)來區(qū)別不同的消息類型。
          使用控件訪問消息隊列的例子
            在本節(jié)中,我們將通過簡單的例子演示如何使用JMS控件來訪問監(jiān)聽消息隊列的消息驅(qū)動Bean。我們假設(shè)存在一個消息驅(qū)動Bean,他接受用戶傳遞的文本消息(TextMessage),隨后將該文本消息打印在應(yīng)用服務(wù)器的控制臺上。該消息驅(qū)動Bean監(jiān)聽消息隊列(jndiname=”queue/helloworld”)。

            Beehive并不僅僅限于WebLogic平臺使用,我們這里以JBoss為例。我們使用Eclipse+WTP(Web Tools Platform)工具開發(fā)符合要求的消息驅(qū)動Bean以及JMS隊列,發(fā)布在JBoss上。

            本文中所有例子的源代碼可以在通過資源下載區(qū)中的連接完成下載。

          開發(fā)消息驅(qū)動Bean
            現(xiàn)在我們來開發(fā)提供上述功能的消息驅(qū)動Bean,使用WTP的向?qū)瓿上Ⅱ?qū)動Bean的創(chuàng)建工作,剩下的工作就是根據(jù)業(yè)務(wù)的需求完成onMessage方法的編寫了。

            根據(jù)演示實例的要求,我們修改onMessage方法,讓它處理TextMessage類型的消息,并且將消息的內(nèi)容打印在控制臺上,清單1中列出了消息驅(qū)動Bean類的源代碼。如何開發(fā)、編譯和部署請參考JBoss的幫助文檔,這里不提供詳細的說明。

            接下來的JMS、EJB開發(fā)、部署和控件訪問部分內(nèi)容針對JBoss應(yīng)用服務(wù)器。實際情況下,你可能根據(jù)不同情況選擇其他的J2EE容器比如Websphere 、WebLogic、Geronimo、JOnAS等作為EJB容器,請根據(jù)下面的提示信息進行適當(dāng)?shù)恼{(diào)整。

            清單1 ejbsrc\org\vivianj\beehive\controls\examples\ejb\MessageBeanOnQueue.java

          1. package org.vivianj.beehive.controls.examples.ejb;
          2. 
          3. import javax.ejb.*;
          4. import javax.jms.*;
          5. 
          6. public class MessageBeanOnQueue
          7.   implements MessageDrivenBean, MessageListener
          8. {
          9.   public void onMessage(Message msg) {
          10.     TextMessage tm = null;
          11.     if (msg instanceof TextMessage){
          12.         tm = (TextMessage) msg;
          13.         try{
          14.         System.out.println(tm.getText());
          15.         }catch(Exception e){
          16.             e.printStackTrace();
          17.         }
          18.     }
          19.   }
          20. }
            在部署消息驅(qū)動Bean之前,我們還應(yīng)該在JBoss服務(wù)器上配置一個JNDI名稱為“queue/helloworld”的消息隊列。請大家參考JBoss應(yīng)用服務(wù)器的幫助文檔完成這部分工作。

          JMS控件開發(fā)
            現(xiàn)在我們來使用JMS控件編寫代碼訪問消息驅(qū)動Bean。由于消息驅(qū)動Bean沒有本地或者遠程訪問方法,只能通過向JMS目標(biāo)發(fā)送消息來完成消息驅(qū)動Bean資源的調(diào)用。

            清單2中的代碼是訪問一個JMS目標(biāo)對列的簡單例子,它提供sendTextMessage方法,接收String類型的參數(shù)msn,當(dāng)sendTextMessage方法被調(diào)用時,控件負責(zé)連接到JMS對列(“queue/helloworld”),將接收到的參數(shù)msg發(fā)送到目標(biāo)服務(wù)器上。

            清單2 src\org\vivianj\beehive\controls\examples\controls\

            HelloWorldQueueJMSControl.java

          1. package org.vivianj.beehive.controls.examples.controls;
          2. 
          3. import org.apache.beehive.controls.api.bean.ControlExtension;
          4. import org.apache.beehive.controls.system.jms.JMSControl;
          5. 
          6. /**
          7. * HelloWorldQueueJMSControl 是訪問JMS資源的控件
          8. * 可向JMS對列發(fā)送字符串類型的消息
          9. */
          10. 
          11. @ControlExtension
          12. @JMSControl.Destination(sendJndiName = “queue/helloworld”,
          13.      jndiConnectionFactory =
          14.         “org.jnp.interfaces.NamingContextFactory”,
          15.      jndiProviderURL=“jnp://localhost:1099”,
          16.      sendType=DestinationType.Queue)
          17. public interface HelloWorldQueueJMSControl
          18.     extends JMSControl {
          19.       @JMSControl.Message(MessageType.Text)
          20.      public void sendTextMessage(String msg);
          21. }
          JMS控件調(diào)用
            現(xiàn)在我們可以使用如下方法來完成上面所創(chuàng)建控件的調(diào)用。

            使用聲明式控件實例化定義成員變量_jmsControl.

             @Control

             HelloWorldQueueJMSControl _jmsControl;

             調(diào)用控件的業(yè)務(wù)方法完成向JMS對列發(fā)送消息的功能。由于消息服務(wù)本身是沒有返回內(nèi)容的,所以我們只需要完成業(yè)務(wù)方法的調(diào)用即可。

            下面的調(diào)用代碼可以實現(xiàn)向服務(wù)器發(fā)送”Hello World!”字符串的功能。

            _jmsControl.sendTextMessage(“Hello World!”);

          測試控件
            一切準(zhǔn)備就緒后,啟動JBoss服務(wù)器,參考《控件入門》中“使用JUnit測試控件”部分的內(nèi)容,編寫單元測試TestCase測試新創(chuàng)建的JMS控件。

          實例分析
            從上面的例子中我們可以看到,訪問JMS資源的時候,開發(fā)者的工作被大大的簡化了。開發(fā)者只需要開發(fā)一個繼承自JMS控件的控件,使用JMS控件中規(guī)定的注釋提供訪問JMS資源所需要的一些環(huán)境參數(shù),隨后便可以使用聲明式控件實例化方式完成控件的實例化,通過調(diào)用該控件實例的相關(guān)業(yè)務(wù)方法完成JMS資源的訪問。

            現(xiàn)在我們來分析一下上面創(chuàng)建的EJB控件-- HelloWorldQueueJMSControl (參見清單2)中的主要代碼。

          11.   @ControlExtension
           在控件例子的11行,我們通過@ControllerExcention關(guān)鍵詞來說明接下來聲明的這個接口是另外一個控件的擴展。
          12.   @JMSControl.Destination(sendJndiName = “queue/helloworld”,
          13.      jndiConnectionFactory =
          14.        “org.jnp.interfaces.NamingContextFactory”,
          15.     jndiProviderURL=“iiop://localhost:7001”,
          16.     sendType=DestinationType.Queue))
            在第12~16行代碼中我們使用JMSControl.Destination關(guān)鍵詞和它的sendJndiName、jndiConnectionFactory、jndiProviderURL和sendType屬性來設(shè)置我們要訪問消息隊列/主題在目標(biāo)服務(wù)器中發(fā)布時使用的jndiName和訪問目標(biāo)服務(wù)器需要提供的相關(guān)環(huán)境變量。

          17.    public interface HelloWorldQueueJMSControl
          18.        extends JMSControl {
           在第17~18行中,我們聲明該控件繼承了JMSControl接口。
          19.   @JMSControl.Message(MessageType.Text)
           在第19行,我們使用@JMSControl.Message關(guān)鍵字來聲明接下來的這個業(yè)務(wù)方法發(fā)送消息的類型是TextMessage。
          20.    public void sendTextMessage(String msg);
             第20行代碼我們聲明了一個方法,這個方法需要向目標(biāo)消息隊列/主題發(fā)送參數(shù)msg提供的字符串。

            完成這些工作,我們就可以調(diào)用該控件聲明的方法實現(xiàn)向目標(biāo)消息隊列/主題發(fā)送JMS消息了,如何與目標(biāo)應(yīng)用服務(wù)器交互的工作由控件來輔助完成。

          使用注釋定制JMS控件
            在上面的內(nèi)容中,我們已經(jīng)新建了一個JMS控件,它提供sendTextMessage方法,調(diào)用該方法能夠向消息對列”queue/helloworld”發(fā)送消息。在JMS控件代碼中,我們使用了@JMSControl.Destination我們使用了@JMSControl.Destination和@JMSControl.Message兩個注釋來提供訪問JMS資源的參數(shù)。

            JMS控件支持10個注釋,他們分別是@JMSControl.CorrelationId、@JMSControl.Delivery 、@JMSControl.Destination 、@JMSControl.Expiration 、@JMSControl.Message 、@JMSControl.Priority 、@JMSControl.Properties 、@JMSControl.Property 、@JMSControl.PropertyValue 、@JMSControl.Type

            下面我們詳細的介紹其中最常用的@JMSControl.Destination和@JMSControl.Message兩個注釋的屬性和用法,了解如何用這注釋定制JMS控件的更多細節(jié)。

          Destination注釋
            Destination注釋是類級別的注釋,用于定制JMS控件發(fā)送消息的目標(biāo)消息隊列/主題的jndiName和它們所在目標(biāo)容器的相關(guān)參數(shù)。Destination注釋提供了八個參數(shù)用于用戶定制,下面將介紹常用的四個:sendJndiName、jndiConnectionFactory、 sendType、jndiProviderURL,其中sendJndiName和jndiConnectionFactory是必須的,其他的可以根據(jù)不同的情況選擇性的使用。

          sendJndiName
            字符串類型的屬性,用于設(shè)置目標(biāo)消息隊列或者主題的JNDI名稱。

          sendType
            JMSControl.DestinationType類型的屬性,可選值有三個:DestinationType.Auto(自動適配類型),DestinationType.Topic(主題)和DestinationType.Queue(隊列),如果使用DestinationType.AUTO,控件將根據(jù)sendJndiName中指定的目標(biāo)消息類型進行適配。

          jndiConnectionFactory
            字符串類型的屬性,設(shè)置訪問EJB JNDI上下文環(huán)境需要使用工廠類,和具體的目標(biāo)EJB服務(wù)器相關(guān)。比如訪問JBoss服務(wù)器上的JMS資源時可以設(shè)置jndiConnectionFactory為“org.jnp.interfaces.NamingContextFactory”。

          jndiProviderURL
            字符串類型的屬性,設(shè)置目標(biāo)EJB容器的相關(guān)屬性,包括訪問JNDI上下文環(huán)境使用的協(xié)議、目標(biāo)服務(wù)器IP地址、服務(wù)端口等,比如訪問JBoss容器中消息隊列時,providerURL可以寫成”jnp://localhost:1099”。

          Message注釋
            Message注釋是JMS控件中方法級別的注釋,它的參數(shù)為JMSControl.MessageType類型,用于注釋新創(chuàng)建JMS控件的業(yè)務(wù)方法,聲明該業(yè)務(wù)方法發(fā)送消息的類型,可選參數(shù)包括MessageType.Text、MessageType. Bytes(字節(jié)類型)、MessageType.Object(對象類型), MessageType.Map (Map類型)、MessageType.JMSMessage(JMS消息類型)、MessageType.Auto(自動適配類型),默認的消息類型是MessageType.Auto。

            如果使用默認的消息類型或者設(shè)置被發(fā)送消息的類型為MessageType.Auto,控件將根據(jù)被發(fā)送消息的類型來決定發(fā)送消息時使用的消息類型:

          如果被發(fā)送的消息是字符串內(nèi)容或者是XML對象,控件將發(fā)送TextMessage類型的消息給目標(biāo)消息隊列/主題;
          如果被發(fā)送的消息內(nèi)容是字節(jié)數(shù)組,控件將發(fā)送StreamMessage類型的消息給目標(biāo)消息隊列/主題;
          如果被發(fā)送的消息內(nèi)容是字節(jié)數(shù)組,控件將發(fā)送StreamMessage類型的消息給目標(biāo)消息隊列/主題;
          如果被發(fā)送的消息內(nèi)容是Map對象,控件將發(fā)送MapMessage類型的消息給目標(biāo)消息隊列/主題;
          如果被發(fā)送的消息內(nèi)容是JMSMessage對象,控件將發(fā)送JMSMessage類型的消息給目標(biāo)消息隊列/主題;
          如果被發(fā)送的消息內(nèi)容實現(xiàn)了Serializable接口,控件將發(fā)送ObjectMessage類型的消息給目標(biāo)消息隊列/主題;
          其他的消息內(nèi)容,控件將不發(fā)送消息,而是拋出一個違例。
          JMS控件內(nèi)置的方法
            JMS控件提供了很多可以在運行時對JMS控件進行定制的Java方法,開發(fā)者使用這些內(nèi)置的方法可以在使用JMS控件的過程中根據(jù)不同的情況靈活的加以應(yīng)用,以便能夠完成各種復(fù)雜的業(yè)務(wù)邏輯。

          getSession()
            獲取當(dāng)前訪問消息隊列/主題的會話對象。

          getDestination()
            獲取當(dāng)前訪問消息隊列/主題的目標(biāo)服務(wù)的相關(guān)信息。

          getConnection()
            獲取當(dāng)前訪問消息隊列/主題和目標(biāo)服務(wù)器之間的連接。

          setHeaders(Map)
          setHeader(HeaderType,Object)
            這兩個方法都用于設(shè)置被發(fā)送消息的頭信息,只有調(diào)用了這兩個方法后接著發(fā)送的消息才使用這部分頭信息,其他的消息不具備這些頭信息。如果發(fā)送的消息中也設(shè)置了同樣的信息,使用setHeaderX方法設(shè)置的參數(shù)將覆蓋消息中設(shè)置的參數(shù)。

            被設(shè)置的頭信息包括JMSCorrelationID、JMSExpriation 、Priority 、JMSType,用于發(fā)送消息時標(biāo)識身份或者提供消息發(fā)送所需要的路由。

          setProperties(Map)
          setProperty(String,Object)
            這兩個方法用于在發(fā)送消息的同時提供更多的屬性信息,可以用于在應(yīng)用中作為擴展頭信息而使用,可發(fā)送的類型可以是boolean, byte, short, int, long, float, double, or String等基本Java數(shù)據(jù)類型。

          結(jié)束語
            JMS是J2EE框架中最重要的部分,也是企業(yè)應(yīng)用中提供異步消息訪問的技術(shù)實現(xiàn),然而JMS的客戶端編寫對于開發(fā)者而言不是一件輕松的事情。控件架構(gòu)中的JMS控件大大的簡化了JMS資源的復(fù)雜性、難度,開發(fā)者只需要通過簡單的繼承org.apache.beehive.controls.system.jms.JMSControl,然后通過提供相應(yīng)的注釋就可以完成JMS資源的訪問。

          posted on 2007-05-06 12:54 張金鵬 閱讀(191) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 咸丰县| 中江县| 泗水县| 会泽县| 应城市| 拜城县| 阿荣旗| 南昌县| 威信县| 景宁| 南投县| 张家口市| 宣城市| 宝鸡市| 扎囊县| 申扎县| 兴业县| 东平县| 偏关县| 北川| 冕宁县| 阳信县| 扬中市| 汉中市| 永城市| 海门市| 博湖县| 临沭县| 深州市| 麟游县| 呼玛县| 华蓥市| 盖州市| 浦北县| 伊金霍洛旗| 南投县| 娱乐| 耿马| 吉木乃县| 桓台县| 南漳县|