細心!用心!耐心!

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

          BlogJava 聯系 聚合 管理
            1 Posts :: 196 Stories :: 10 Comments :: 0 Trackbacks

          快速應用JMS控件訪問JMS資源

           

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

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

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

            你可以使用下面的步驟來創建自己的控件實現對JMS資源的訪問:

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

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

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

          開發消息驅動Bean
            現在我們來開發提供上述功能的消息驅動Bean,使用WTP的向導完成消息驅動Bean的創建工作,剩下的工作就是根據業務的需求完成onMessage方法的編寫了。

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

            接下來的JMS、EJB開發、部署和控件訪問部分內容針對JBoss應用服務器。實際情況下,你可能根據不同情況選擇其他的J2EE容器比如Websphere 、WebLogic、Geronimo、JOnAS等作為EJB容器,請根據下面的提示信息進行適當的調整。

            清單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. }
            在部署消息驅動Bean之前,我們還應該在JBoss服務器上配置一個JNDI名稱為“queue/helloworld”的消息隊列。請大家參考JBoss應用服務器的幫助文檔完成這部分工作。

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

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

            清單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對列發送字符串類型的消息
          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控件調用
            現在我們可以使用如下方法來完成上面所創建控件的調用。

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

             @Control

             HelloWorldQueueJMSControl _jmsControl;

             調用控件的業務方法完成向JMS對列發送消息的功能。由于消息服務本身是沒有返回內容的,所以我們只需要完成業務方法的調用即可。

            下面的調用代碼可以實現向服務器發送”Hello World!”字符串的功能。

            _jmsControl.sendTextMessage(“Hello World!”);

          測試控件
            一切準備就緒后,啟動JBoss服務器,參考《控件入門》中“使用JUnit測試控件”部分的內容,編寫單元測試TestCase測試新創建的JMS控件。

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

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

          11.   @ControlExtension
           在控件例子的11行,我們通過@ControllerExcention關鍵詞來說明接下來聲明的這個接口是另外一個控件的擴展。
          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關鍵詞和它的sendJndiName、jndiConnectionFactory、jndiProviderURL和sendType屬性來設置我們要訪問消息隊列/主題在目標服務器中發布時使用的jndiName和訪問目標服務器需要提供的相關環境變量。

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

            完成這些工作,我們就可以調用該控件聲明的方法實現向目標消息隊列/主題發送JMS消息了,如何與目標應用服務器交互的工作由控件來輔助完成。

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

            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控件的更多細節。

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

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

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

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

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

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

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

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

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

          getDestination()
            獲取當前訪問消息隊列/主題的目標服務的相關信息。

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

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

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

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

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

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

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


          網站導航:
           
          主站蜘蛛池模板: 定结县| 南昌市| 尉犁县| 辉县市| 庄浪县| 石台县| 依安县| 商都县| 清水河县| 饶平县| 盱眙县| 于田县| 汝阳县| 北宁市| 隆安县| 镇江市| 榆林市| 肥西县| 翁牛特旗| 美姑县| 怀远县| 白朗县| 抚宁县| 高邮市| 武定县| 乌鲁木齐县| 咸丰县| 商南县| 灵石县| 多伦县| 汶上县| 黄梅县| 石城县| 宁波市| 新绛县| 屏山县| 恩施市| 临猗县| 平武县| 万年县| 二手房|