在分佈式企業級應用程序中,異步消息機制用於有效地協調各個部分的工做。
J2EE爲咱們提供了JMS和消息驅動Bean(Message-Driven Bean),用來實現應用程序各個部件之間的異步消息傳遞。
一.什麼是消息系統?
一般一個消息系統容許分開的未耦合的應用程序之間可靠地異步通訊。在企業應用時,須要一種異步的,非阻塞的消息傳遞。好比,一個客戶端可能但願給一個服務器發送一個請求後,不在意是否立刻能獲得迴應。這樣,客戶端沒有理由必須等待服務器處理請求。客戶端應用程序在遞交一個請求以後,只需確保請求到達服務器端後,就能夠處理其餘任務。一般,這是很高效的。消息系統提供了許多其餘分佈式對象計算模型沒有的優勢。它鼓勵在消息產生者和使用者之間的"鬆耦合",在它們之間有很高程度的事務處理。對於使用者,它不在意誰產生了消息,產生者是否仍在網絡上以及消息是何時產生的。這就容許創建動態的,可靠的和靈活的系統。整個的子系統能被修改而不會影響系統的其餘部分。
另外的優勢包括:系統的高度可擴展性,容易與其餘系統進行集成,以及高度的可靠性。因爲可靠性和可擴展性,使得它們用於解決許多商業和科學計算問題。好比,消息系統是許多應用程序的基礎,這些應用程序能夠是工做流,網絡管理,通訊服務或供應鏈管理程序。在JAVA技術中,處理異步消息的能力是經過JMS來實現的。JMS最初設計是爲了給傳統的消息對象中間件提供一個標準的JAVA接口。而這些產品是在一個企業級應用程序中必須的。如今出現了許多支持JMS的純JAVA的產品。
消息系統類型
一般有兩種消息類型。
1.發佈/訂閱(publish/subscribe)
發佈/訂閱消息系統支持一個事件驅動模型,消息產生者和使用者都參與消息的傳遞。產生者發佈事件,而使用者訂閱感興趣的事件,並使用事件。產生者將消息和一個特定的主題(Topic)連在一塊兒,消息系統根據使用者註冊的興趣,將消息傳給使用者。
2.點對點(Peer to peer)
在點對點的消息系統中,消息分發給一個單獨的使用者。它維持一個"進入"消息隊列。消息應用程序發送消息到一個特定的隊列,而客戶端從一個隊列中獲得消息。
二.JMS簡介
JMS的目的是提供給消息系統客戶一個固定的接口,並且與底層的消息提供者無關。這樣,客戶端的應用程序能夠在不一樣的機器和操做系統中移植,並且能在不一樣的消息系統產品之間轉移。JMS客戶端都是創建在JAVA技術上的,從而也能使用其餘JAVA API,如JDBC數據庫鏈接,使用JAVA BEAN組件模型,JDNI名字服務,JTA客戶端事務處理控制以及J2SE和J2EE API來實現企業級應用服務程序。
1.JMS對象模型
圖1顯示了JMS對象,用於提供JMS客戶端與JMS服務提供者相連的對象。
feedom.net國內最先的網管網站
ConnectionFactory是一個客戶端用來建立一個Connection的管理對象。因爲在Connection建立時有受權和通訊創建過程,所以這個對象是比較大的。
Destination對象將一個消息的目的和服務提供者有關的地址及配置信息包裝起來。
Session是JMS實體,用來支持事務處理和異步消息消費。JMS並不須要客戶端的代碼用於異步消息消費或能處理多個併發消息。一般,事務的複雜性都由一個Session來封裝。
一個Session是一個原子單位的工做,與數據庫的事務同樣,要實現多線程事務比較困難。Session提供了在一個線程編程模式下的併發的優勢。
MessageProducer和MessageConsumer對象由Session對象建立。用於發送和接受消息。爲了確保消息的傳遞,JMS服務提供者處理的消息都要處於PERSISTENT模式。PERSISTENT模式使得JMS提供者出問題後,也能讓消息保存下來。
Session,MessageProducer和MessageConsumer都不支持併發,而ConnectionFactory,Destination和Connection都支持併發。
2.JMS應用程序開發
JMS中的消息
在消息系統中,應用程序之間通訊的關鍵是消息。所以使用JMS必需要先理解消息。
在JMS中,消息由三部分組成:
MESSAGE HEADER用於識別消息,好比用於判斷一個給定的消息是不是一個"訂閱者"
PROPERITIES用於與應用程序相關的,提供者相關的和可選項的信息
BODY是消息的內容,支持幾種格式,包括TextMessage(對String一個簡單的封裝)和ObjectMessage(對任意對象的封裝,但必須支持序列化),也支持其餘格式。
TextMessage
一個TextMessage是一個String對象的封裝。在只有文本對象傳遞時,是頗有用的。它假設許多消息系統是創建在XML上的。從而TextMessage就能夠成爲包裝它們的容器。
建立一個TextMessage對象很簡單,以下面的代碼:
TextMessage message=session.createMessage();
message.setText("Hello, world!");
ObjectMessage
如名字所示,它是對一個JAVA對象的封裝的消息。任何可序列化的JAVA對象都能用於ObjectMessage,若是必須將多個對象封裝在一個消息裏傳遞,可使用Collection對象,來包括多個序列化對象。
下面是建立一個ObjectMessage
ObjectMessage message=session.createObjectMessage();
message.setObject(myObject);
建立一個JMS客戶端程序
一個典型的JMS客戶端由下面的幾個基本步驟來建立:
建立一個到消息系統提供者的鏈接(Connection)
bitsCN.com中國網管聯盟
建立一個Session,用於接收和發送消息
建立MessageProducer和MessageConsumer來建立和接收消息
當完成了上述步驟後,一個消息產生者客戶端將建立併發布消息到一個主題,而消息使用者客戶端會接收與一個主題相關的消息。
1.建立一個Connection
一個Connection提供客戶端對底層的消息系統的訪問。並實現資源的分配和管理。經過使用一個ConnectionFactory來建立一個Connection,一般用JDNI來指定:
2.建立一個Session
Session是一個比較大的JMS對象,他提供了生產和消費消息的手段。用於建立消息使用者和消息產生者。
topicSession = topicConnection.createTopicSession(false,Session.AUTO_ACKNOWLEDGE);
兩個參數用於控制事務和消息確認。
3.定位一個Topic
用JDNI來定位一個Topic,Topic用於識別發送或接收的消息,在發佈/訂閱系統中。訂閱者訂閱一個給定的Topic,而發佈者將它發佈的消息與一個Topic相連。
下面是建立一個Topic "WeatherReport"
Topic weatherTopic=messaging.lookup("WeatherReport");
4.啓動Connection
在上面的初始化步驟以後,消息流是禁止的,用於防止在初始化時發生不可預料的行爲。一旦初始化結束,必須讓Connection啓動消息系統。
topicConnection.start();
5.建立一個消息產生者
在發佈/訂閱裏,一個產生者發佈消息到一個指定的Topic。下面的代碼顯示建立一個產生者,以及後續的創建和發佈一個簡單文本消息。
TopicPublisher publisher=session.createPublisher(weatherTopic);
TexeMessage message=session.createMessage();
message.setText("ssss");
publisher.publish(message);
下面是一個消息使用者的代碼
三.消息驅動Bean簡介
異步消息也能夠由消息驅動Bean來實現。在EJB 1.1規範中,定義了兩種類型的EJB。分別是實體Bean(Entity Bean)和會話Bean(Session Bean)。客戶端一般是以同步的,阻塞方式來調用Bean的方法。消息驅動Bean將EJB和JMS的功能結合在一塊兒。
正如前述,會話Bean一般實現商務邏輯,客戶端不能共享一個會話Bean。實體Bean一般和一些在永久存儲中的一些實體條目相對應的。這兩種Bean一般都有REMOTE和HOME接口,用來與客戶端交互。而且,這些交互都是同步的,阻塞方式進行的。好比,一個請求發送給一個Bean,經過阻塞式方法調用,服務器返回一個相應。調用者在收到返回後,才能進行下一步處理。消息驅動Bean一般配置成是一個特別的主題(topic)或隊列的客戶端,做爲消息的使用者。但消息驅動Bean沒有HOME和REMOTE接口。一個消息產生者將消息寫入TOPIC或隊列時,並不知道使用者是一個消息驅動Bean。這就容許集成一個分佈式的計算系統時,有很大的靈活性。消息驅動Bean沒有會話性質的狀態,全部的實例在不處理請求時是相同的,這與無狀態會話Bean是相似的。將Bean的實例放在緩衝池裏,也是高效處理消息驅動Bean的一種方法。一個消息驅動Bean必須間接或直接地從javax.ejb.MessageDrivenBean接口繼承而來。這個接口是由javax.jms.MessageListener繼承而來。這個方法的一個參數是javax.jms.Message。能夠是任何有效的JMS消息類型。方法的申明中並不包含一個thrown語句。所以在消息處理中,不會仍出應用程序異常。當容器接收到消息時,它首先是從一個緩衝池裏獲得現成的一個消息驅動Bean,而後,若是配置文件須要的,容器還要設置一個和事務處理上下文的一個聯繫。當這些管理任務完成時,接收到的消息傳遞給onMessage()方法。一旦方法完成,事務確認或返回,Bean又被從新放回到緩衝池。
bbs.bitsCN.com國內最先的網管論壇 ejbRemove()在把消息驅動Bean從任何存儲上刪除時調用。並進行清楚操做和垃圾收集。必須在ejbRemove()方法中釋放全部Bean的實例用到的資源。