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

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

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

    細心!用心!耐心!

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

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

    使用JMS隊列

    Java消息發(fā)送服務(Java Messaging Service,JMS)是提供商無關(guān)的一套API,用于在程序間進行可靠的消息發(fā)送。在客戶端-服務器計算中,客戶端程序與服務器與服務器建立聯(lián)系并請求服務。相反,消息發(fā)送應用在相互協(xié)作的程序之間發(fā)送消息。有些程序(在所謂的“對等(peer-to-peer)”應用中)則相互之間直接交換信息(JXTA使用的就是這種模型)。

    JMS提供了一個中間件消息代理(message broker),后者提供了程序間可靠的、事務性的消息發(fā)送。

    雖然這些圖中顯示的消息提供者和消費者都是物理上的機器,實際上它們也可以是運行在一臺或者多臺機器上的相互協(xié)作的一些進程。

    JMS提供者是一個程序,它實現(xiàn)了JMS公共接口中的JMS服務約定。J2EE平臺規(guī)范要求平臺實現(xiàn)包含一個JMS提供者。

    大多數(shù)人都比較熟悉客戶端-服務器模型的消息發(fā)送,在這種模型中,客戶端程序與服務器建立聯(lián)系,請求服務、數(shù)據(jù),或者同時請求服務和數(shù)據(jù)。相反,JMS提供了一種更豐富的消息發(fā)送模型,這種模型具有以下高級特性:

    可靠的消息發(fā)送。當消息發(fā)送者正在發(fā)送消息時,消息接受者無需處于運行狀態(tài)。而是等等接受者下次做好準備時,再將消息發(fā)送到接受者手上。
    點到點或者發(fā)布/訂閱式的消息發(fā)送模型。消息的傳送可能是一對一的,也可能是一對多的。
    事務。消息發(fā)送可作為一個分布式事務的一部分。
    同步的或異步的消息發(fā)送。消息生產(chǎn)者可能會等待接受者的確認,也可能不會。
    面向?qū)ο蟮南l(fā)送。JMS允許在客戶端之間發(fā)送對象,而不是通過使用一些協(xié)議來發(fā)送結(jié)構(gòu)化的數(shù)據(jù)。
    遺留整合。JMS可以與底層的第三方消息發(fā)送系統(tǒng)進行整合。
    本期解釋了如何使用JMS消息隊列來實現(xiàn)兩個進程之間簡單、可靠的點到點的消息發(fā)送。發(fā)布/訂閱式的消息發(fā)送將在后面的期“Enterprise Java Technologies Tech Tips”中講述。

     

    JMS隊列術(shù)語

    JMS使用消息隊列的概念來實現(xiàn)點到點的消息發(fā)送。在點到點的消息發(fā)送中,總是有一個明確的消息生產(chǎn)者和一個消息消費者。在點到點的消息發(fā)送中,與時間沒有多大的關(guān)系,除非消息發(fā)送者為消息定義了一個期限。消息接受這可以接收由消息生產(chǎn)者在過去任何一個時候發(fā)送的消息,即使在該消息被編入隊列時消息消費者沒有處于運行狀態(tài)。

    JMS提供者是一個消息發(fā)送服務器,它負責處理消息的持久性、超時、重發(fā)、事務回滾以及由JMS提供的其他服務。對于J2EE SDK這種情況,JMS提供者是J2EE服務器程序的一部分。消息生產(chǎn)者發(fā)送對象到由JMS維護的一個隊列中。消息消費者則從該隊列接收消息,并發(fā)出確認,表示已經(jīng)收到消息。

    JMS規(guī)范定義了一些可用于在進程間發(fā)送消息的對象:

    JMS管理的對象。有兩種JMS管理的對象:目的地和連接工廠。這兩種對象都是由系統(tǒng)管理員通過環(huán)境管理工具創(chuàng)建的。
    目的地。這是一種服務器端的對象,通過這個對象進行消息的發(fā)送和接收。JMS隊列就是一種目的地對象。
    連接工廠。這是一種服務器端的對象,負責配置和創(chuàng)建到一個特定目的地的連接。JMS 隊列的JMS連接工廠就是一種QueueConnectionFactory。
    連接。這是一種到一個JMS提供者(而不是到一個目的地)的虛擬連接。它被用來創(chuàng)建會話。用于訪問隊列的一個連接就是一種QueueConnection。
    會話。這是一個潛在的消息傳送和接收的事務性的工作單元。會話用于創(chuàng)建消息、消息生產(chǎn)者和消息消費者。用于訪問隊列的一個會話就是一種QueueSession。
    消息。這是一種可以從消息目的地發(fā)送到消息消費者的對象。消息的類型隨要發(fā)送的對象類型的不同而不同。例如,為本期提供的示例代碼就使用了TextMessage對象。
    消息生產(chǎn)者。這是一種由JMS客戶端程序使用的、用于發(fā)送消息到目的地的對象。JMS客戶端程序從一個會話中獲取消息生產(chǎn)者對象。程序可以使用QueueSender這種類型的消息生產(chǎn)者對象來發(fā)送消息到一個隊列中。

    消息消費者。這是一種由JMS客戶端程序使用的、用于從一個目的地接收消息的對象。JMS客戶端程序從一個會話中獲取消息接受者對象。程序可以使用QueueReceiver這種類型的消息消費者對象來從一個隊列中接收消息。
    這里頗有幾個新的術(shù)語。現(xiàn)在讓我們看看如何發(fā)送消息。以下步驟展示了從與本期一起提供的示例代碼中抽出的一些例子。(想知道如何下載和運行該示例代碼,請參考運行示例代碼一節(jié)。)不過,在運行示例代碼之前,你需要配置一下服務器(參見 配置服務器一節(jié))。


    發(fā)送消息

    J2EE參考實現(xiàn)預先配有一個隊列連接工廠(名為QueueConnectionFactory)和一個隊列(名為jms/Queue)。如果你使用的是JMS服務器,而不是參考實現(xiàn),或者如果你想試著更改隊列連接工廠和/或隊列隊列的名稱,請參考配置服務器一節(jié)。

    下面是通過一個JMS隊列發(fā)送消息的步驟。從示例程序TestQueue中抽出的代碼片段也穿插在這些步驟中。

    通過按名字在JNDI中進行查找,獲得一個指向QueueConnectionFactory 的引用:

        protected static String qfactoryName =3.
                "jms/queue/TechTipsQueueConnectionFactory";4.
             ...
             try {
             // 獲得JNDI上下文
             InitialContext ctx = new InitialContext();
             // 獲得連接工廠
             QueueConnectionFactory qcf =
             (QueueConnectionFactory)ctx.lookup(qfactoryName);


    2.從 QueueConnectionFactory獲得一個QueueConnection,再從這個連接獲得一個QueueSession 。按名字在JNDI中查找:


          // 獲得一個到隊列的連接
           qc = qcf.createQueueConnection();
           //從該連接獲得一個會話
           QueueSession qs = qc.createQueueSession(
               false, Session.AUTO_ACKNOWLEDGE);
          // 獲得一個隊列
          Queue q = (Queue)ctx.lookup(queueName);

    3. 使用QueueSession創(chuàng)建一個QueueSender,將該隊列作為一個參數(shù)來傳遞。(QueueSender是QueueSession與某個特定隊列之間的一個關(guān)聯(lián)。):


          // 使用這個會話創(chuàng)建一個QueueSender 
          // and a TextMessage.
          QueueSender qsnd = qs.createSender(q);


    現(xiàn)在可以用QueueSender來發(fā)送消息到隊列。

    4. 創(chuàng)建一個消息對象(Message的子類),然后使用QueueSender的發(fā)送方法將它們發(fā)送至目的地。示例程序從Session中獲得一個TextMessage對象。接著示例程序?qū)⒚總€程序參數(shù)打包到TextMessage 中,然后使用QueueSender將其發(fā)送至隊列。注意,同一個TextMessage 可以使用多次。


          TextMessage tm = qs.createTextMessage();
           
          // 為第一個參數(shù)之后的每個參數(shù)進行一次循環(huán)
          // 以文本消息的形式發(fā)送參數(shù)字符串
          for (int i = 2; i < args.length; i++) {
              tm.setText(args[i]);
              qsnd.send;
          }

    5.關(guān)閉QueueConnection。在try/finally程序塊的最后一條語句中關(guān)閉連接是一個好習慣。這一步很重要:忘記關(guān)閉 QueueConnections 將可能導致服務器上的資源泄漏:


      } finally {
              if (qc != null) {
                  qc.close();

              }
          }


    要發(fā)送消息到一個消息隊列,可以使用TestQueue程序(在缺省的包中),加上一個參數(shù)“send”,例如:

    $ java TestQueue send jms/queue/MyTestQueue a b c d
    Java Message Service 1.0.2 Reference
    Implementation (build b14)
    Sent: 'a'
    Sent: 'b'
    Sent: 'c'
    Sent: 'd'


    接收消息

    TestQueue程序按照以下步驟接收消息:

    和2從一個消息隊列接收消息的起先兩步與發(fā)送消息是一樣的:先是查找連接工廠,再獲得一個QueueConnection,然后查找Queue。
    從QueueSession 獲得一個QueueReceiver :
    QueueReceiver qrcv = qs.createReceiver(q);
    3.    從Queue接收消息。示例程序進入一個循環(huán),在這個循環(huán)中從隊列獲取消息并將它們打印到標準輸出設備。


             qc.start();
             Message m = qrcv.receive(10000);
             while (m != null) {

                 if (m instanceof TextMessage) {
                     TextMessage tm = (TextMessage)m;
                  System.out.println("Received text: '" +
                                     tm.getText() + "'");
              } else {
                  System.out.println("Received a " +
                                  m.getClass().getName());
              }
              m = qrcv.receive(100);
          } finally {
             if (qc != null) {
                 qc.close();
              }
          }

    對QueueConnection的啟動方法的調(diào)用將告訴連接開始接收消息。QueueReceiver接收方法帶有一個參數(shù),該參數(shù)表明了等待一條消息的毫秒數(shù)。如果消息沒有在規(guī)定時間內(nèi)到達,該方法將返回null值。直到消息隊列在100毫秒的時間內(nèi)都保持為空,程序才開始讀取和打印收到的消息。在try/finally程序塊的結(jié)尾有一個finally子句,該子句像前面例子中一樣地關(guān)閉QueueConnection。

    要接收消息隊列中的消息,可以使用TestQueue程序,再帶上一個參數(shù)“recy”,例如:

    $ java TestQueue recv jms/queue/MyTestQueue
    Java Message Service 1.0.2 Reference
    Implementation (build b14)
    Received text: 'a'
    Received text: 'b'
    Received text: 'c'
    Received text: 'd'


    配置服務器

    如果你使用的不是參考引用,或者你想更改隊列和/或隊列連接工廠的名字,你就需要通過使用平臺的管理工具配置JMS提供者。隊列或者連接工廠被創(chuàng)建之后,便留在服務器中,直到服務器重新啟動。有些平臺實現(xiàn)可能會為客戶端提供擴展API,以便程序化地創(chuàng)建目的地和連接工廠。

    用來在J2EE SDK下創(chuàng)建受管理的對象的工具是。要配置服務器,需:

    啟動應用服務器。
    Create a message queue, giving it a JNDI name. (Do this only once.) To create a
    new message queue in the J2EE SDK, first decide on a name for your message
    queue. It can be convenient for administration purposes to choose a name that
    indicates that the queue is used by JMS, for example, jms/MyTestQueue. Then
    execute the command:創(chuàng)建一個消息隊列,并為它取一個JNDI名。(只做一次。)要用J2EE SDK創(chuàng)建一個新的消息隊列,首先需要為消息隊列決定一個名字。為了便于管理, 應該選擇一個可以表明該隊列是JMS使用的隊列,例如jms/MyTestQueue。然后執(zhí)行命令:
                 j2eeadmin -addJmsDestination <queuename> queue

    用消息隊列的實際名字替換<queuename> 。

    由于連接工廠名QueueConnectionFactory被硬性地放在示例程序中,因此要告訴程序使用一個不同的連接工廠名,就必須修改源代碼,并且重新編譯。例如,在TestQueue.java中:

            // Change this variable's value to change the 
           // connection factory name
           protected static String qfactoryName =
                              "QueueConnectionFactory"


    重新編譯之后,使用j2eeadmin(或者你自己的服務器的工具)創(chuàng)建一個connection factory,給它取個JNDI名,如:

    j2eeadmin -addJmsFactory jms/MyQueueConnectionFactory

    要列出連接工廠,使用:

    j2eeadmin -listJmsFactory

    要列出目的地,使用:

    j2eeadmin -listJmsDestination

    對于不是J2EE SDK的平臺,可以在該平臺上使用J2EE產(chǎn)品的部署工具來創(chuàng)建所需的消息隊列和連接工廠。


    運行示例代碼

    下載這些期的示例存檔。這個JAR文件包含了示例程序的完整源代碼,包括Java程序文件和HTML格式的文件。你可以使用命令jar xvf ttmar2003.jar 將示例jar中的內(nèi)容解壓縮到你的工作目錄下。在運行示例程序前,要確保J2EE服務器正在運行。

    多次運行示例程序。試著發(fā)送一些成批的消息,但是不接收這些消息,檢查一下輸出的順序。

    這個示例程序為你試著使用JMS隊列提供了切入點。探索一下JMS接口使用的API。例如,可以更改一下程序,試著使用三種不同的接收方式。探索一下事務性的消息發(fā)送,或者試著發(fā)送各種類型的消息對象。JMS有許多特性,熟練使用它可以提高你的應用設計水平。

    posted on 2007-05-06 11:36 張金鵬 閱讀(205) 評論(0)  編輯  收藏

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


    網(wǎng)站導航:
     
    主站蜘蛛池模板: 少妇亚洲免费精品| 精品亚洲福利一区二区| 免费阿v网站在线观看g| 国产精一品亚洲二区在线播放| 日韩成人免费视频| 九九免费观看全部免费视频| 亚洲精品成人久久| 亚洲人成电影在线播放| 69堂人成无码免费视频果冻传媒| 日韩亚洲综合精品国产| 亚洲bt加勒比一区二区| 国产乱辈通伦影片在线播放亚洲| 拍拍拍又黄又爽无挡视频免费| 另类免费视频一区二区在线观看| 国产精品亚洲综合天堂夜夜| 亚洲一级毛片在线观| 亚洲国产高清视频在线观看| 相泽亚洲一区中文字幕| 吃奶摸下高潮60分钟免费视频| 9久9久女女免费精品视频在线观看| 色猫咪免费人成网站在线观看| 精品国产免费一区二区三区| 一级成人毛片免费观看| j8又粗又长又硬又爽免费视频| 免费人成视频在线观看免费| jzzijzzij在线观看亚洲熟妇| 亚洲高清一区二区三区| 亚洲AV无码专区在线电影成人 | 亚洲中文无码永久免费| 国产成人精品一区二区三区免费| 国产vA免费精品高清在线观看| 一级免费黄色毛片| 久久久免费精品re6| 成年丰满熟妇午夜免费视频| 免费一看一级毛片人| 精品国产亚洲一区二区三区| 亚洲精品国产福利片| 在线视频亚洲一区| 免费精品99久久国产综合精品| 久久99九九国产免费看小说| 国产三级电影免费观看|