訊息服務簡介
Java 訊息服務(Java Message Service,JMS)是一種與廠商無關的 API,用來訪問訊息收發系統。它類似於 JDBC (Java Database Connectivity):這裡,JDBC 是可以用來訪問許多不同關係資料庫的 API,而 JMS 則提供同樣與廠商無關的訪問方法,以訪問訊息收發服務。許多廠目前都支持 JMS,包括 IBM 的 MQSeries、BEA的 Weblogic JMS service和 Progress 的 SonicMQ,這只是幾個例子。 JMS 使您能夠通過訊息收發服務(有時稱為訊息中介程式或路由器)從一個 JMS 客戶機向另一個 JML 客戶機傳送訊息。訊息是 JMS 中的一種類型對象,由兩部分組成:報頭和訊息主體。報頭由路由信息以及有關該訊息的元數據組成。訊息主體則攜帶著應用程式的數據或有效負載。根據有效負載的類型來劃分,可以將訊息分為幾種類型,它們分別攜帶:簡單文本 (TextMessage)、可序列化的對象 (ObjectMessage)、屬性集合 (MapMessage)、位元組流 (BytesMessage)、原始值流 (StreamMessage),還有無有效負載的訊息 (Message)。
通信傳遞的訊息交換了計算機之間至關重要的數據——而非用戶之間——並且包含了例如事件通知和服務請求之類的信息。通信通常用來協調在不同的系統中或是用不同的程式語言所寫的程式。
使用JMS接口,程式設計師可以調用IBM的MQSeries,Progress Software的SonicMQ和其他流行通信產品商家的訊息服務。另外,JMS支持包含串列Java對象的訊息和包含可擴展標記語言(XML)頁面的訊息。
模式
Java 訊息服務的規範包括兩種訊息模式,點對點和發布者/訂閱者。許多提供商支持這一通用框架因此,程式設計師可以在他們的分散式軟體中實現面向訊息的操作,這些操作將具有不同面向訊息中間件產品的可移植性。
Java 訊息服務支持同步和異步的訊息處理,在某些場景下,異步訊息是必要的;在其他場景下,異步訊息比同步訊息操作更加便利。
Java 訊息服務支持面向事件的方法接收訊息,事件驅動的程式設計現在被廣泛認為是一種富有成效的程式設計範例,程式設計師們都相當熟悉。
在套用系統開發時,Java 訊息服務可以推遲選擇面對訊息中間件產品,也可以在不同的面對訊息中間件切換。
異步訊息收發
訊息收發系統是異步的,也就是說,JMS 客戶端可以傳送訊息而不必等待回應。比較可知,這完全不同於基於 RPC 的(基於遠程過程的)系統,如 EJB 1.1、CORBA 和 Java RMI 的引用實現。在 RPC 中,客戶機調用伺服器上某個分散式對象的一個方法。在方法調用返回之前,該客戶機被阻塞;該客戶機在可以執行下一條指令之前,必須等待方法調用結束。在 JMS 中,客戶機將訊息傳送給一個虛擬通道(主題或佇列),而其它 JMS 客戶機則預訂或監聽這個虛擬通道。當 JMS 客戶機傳送訊息時,它並不等待回應。它執行傳送操作,然後繼續執行下一條指令。訊息可能最終轉發到一個或許多個客戶機,這些客戶機都不需要作出回應。
JMS 的通用接口集合以異步方式傳送或接收訊息。異步方式接收訊息顯然是使用間斷網路連線的客戶機,諸如行動電話和PDA的最好的選擇。另外, JMS 採用一種寬鬆結合方式整合企業系統的方法,其主要的目的就是創建能夠使用跨平台數據信息的、可移植的企業級應用程式,而把開發人力解放出來。
傳遞訊息方式
JMS 有兩種傳遞訊息的方式。標記為 NON_PERSISTENT 的訊息最多投遞一次,而標記為 PERSISTENT 的訊息將使用暫存後再轉送的機理投遞。如果一個 JMS 服務離線,那么持久性訊息不會丟失,但是得等到這個服務恢復在線上時才會被傳遞。所以默認的訊息傳遞方式是非持久性的。即使使用非持久性訊息可能降低內務和需要的存儲器,並且這種傳遞方式只有當你不需要接收所有的訊息時才使用。
雖然 JMS 規範並不需要 JMS 供應商實現訊息的優先權路線,但是它需要遞送加快的訊息優先於普通級別的訊息。JMS 定義了從 0 到 9 的優先權路線級別,0 是最低的優先權而 9 則是最高的。更特殊的是 0 到 4 是正常優先權的變化幅度,而 5 到 9 是加快的優先權的變化幅度。舉例來說: topicPublisher.publish (message, DeliveryMode.PERSISTENT, 8, 10000); //Pub-Sub 或 queueSender.send(message, DeliveryMode.PERSISTENT, 8, 10000);//P2P 這個代碼片斷,有兩種訊息模型,映射遞送方式是持久的,優先權為加快型,生存周期是10000 (以毫秒度量 )。如果生存周期設定為零,這則訊息將永遠不會過期。當訊息需要時間限制否則將使其無效時,設定生存周期是有用的。
訊息正文格式
JMS 定義了五種不同的訊息正文格式,以及調用的訊息類型,允許你傳送並接收以一些不同形式的數據,提供現有訊息格式的一些級別的兼容性。
· StreamMessage -- Java原始值的數據流
· MapMessage--一套名稱-值對
· TextMessage--一個字元串對象
· ObjectMessage--一個序列化的 Java對象
· BytesMessage--一個未解釋位元組的數據流
JMS應用程式接口提供用於創建每種類型訊息和設定荷載的方法例如,為了在一個佇列創建並傳送一個TextMessage實例,你可以使用下列語句: TextMessage message = queueSession.createTextMessage(); message.setText(textMsg); 以異步方式接收訊息,需要創建一個訊息監聽器然後註冊一個或多個使用MessageConsumer的JMS MessageListener接口。會話(主題或佇列)負責產生某些訊息,這些訊息被傳送到使用onMessage方法的監聽者那裡。 import javax.jms.*; public class ExampleListener implements MessageListener { //把訊息強制轉化為TextMessage格式 public void onMessage(Message message) { TextMessage textMsg = null; // 打開並處理這段訊息 } } 當我們創建QueueReceiver和TopicSubscriber時,我們傳遞訊息選擇器字元串: //P2P QueueReceiver QueueReceiver receiver; receiver = session.createReceiver(queue, selector); //Pub-Sub TopicSubscriber TopicSubscriber subscriber; subscriber = session.createSubscriber(topic, selector);
為了啟動訊息的交付,不論是Pub/Sub還是P2P,都需要調用start方法。
當一條訊息被捕捉時,這條訊息做為一條必須被強制轉化為適當訊息類型的普通Message對象到達。這是一個被用來提取或打開訊息內容的getter方法。下列代碼片段使用StreamMessage類型。 private void unPackMessage (Message message) { String eName; String position; double rate; StreamMessage message; Message = session.createStreamMessage( ); //注意下面的代碼必須按照我給出的順序書寫 message.writeString(eName); message.writeString(position); message.writeDouble(rate); //實現處理訊息的必要的程式邏輯 }
停止訊息的傳遞,無論是Pub/Sub還是P2P,都調用stop方法。 TopicConnection.start( ); //pub-sub QueueConnection.start( ); //P2P TopicConnection.start ( );// pub-sub QueueConnection.start ( );// P2P 其他的J2EE組件--servlet或EJB--可以當作訊息生產者;然而,它們可能只能同步操作,這可能是因為它們的請求-應答的性質決定的。雖然XML目前還不是被支持的訊息類型,傳送一個XML檔案和創建一條文本類型訊息以及把XML檔案添加到訊息的有效負載都一樣簡單,都是以非專有的方式傳送數據。值得注意的是,一些JMS供應廠商已經提供了可用的XML訊息類型。但是使用非標準的訊息類型可能會出現可移植性問題。 String reportData; //reportData內容為XML 文檔 TextMessage message; message = session.createTextMessage(); message.setText (reportData);
訊息驅動組件
MDB 是一個當訊息到達時被容器調用的異步訊息消費程式。與 entity 和 session EJB 不同,MDB 沒有本地和遠程接口並且是匿名的;它們對於客戶是不可見的。MDB 是 JMS 系統的一部分,作為消費者實現伺服器上的商業邏輯程式。 一個客戶程式可能通過使用 JNDI 定位一個與 MDB 相關聯的 JMS。 例如: Context initialContext = new InitialContext(); Queue reportInfoQueue = (javax.jms.Queue)initialContext.lookup (“java:comp/env/jms/reportInfoQueue”); MDB是由Bean類和相應的XML部署描述符組成。 Bean 類實現MessageDriveBean 接口: import javax.ejb.*; import jms.Message.*; public interface MessageDriveBean { public void ejbCreate(); public void ejbRemove(); public void setMessageDrivenContext(MessageDrivenContext ctx); } 訊息監聽器接口: import javax.jms.*; public interface MessageListener { public void onMessage( ); }
使用舉例
既然我現在已經有了一些基本的 JMS知識,那么我們可以使用 JMS 做什麼呢?任何事情都可以。例如,分別用於銷售、庫存、客戶服務和賬目處理的系統。這些部門之間的系統很可能已經存在了很長時間,這些處理要求把事務移動到系統中去,這並不是一個小的工作。這就是訊息服務適用的地點。
當售貨員完成銷售的時候,一條訊息被發給庫存系統;一旦訂單訊息傳送給收發貨人員,就可以按照訂單出貨了。當訂單成功地發貨,系統將通知顧客服務和會計系統這個訂單已經成功的交易了。所有對應的每個子系統都自動地根據收到的訊息進行更新。
JMS 一般都不是用來整合一個系統,而是整合許多可能參與訊息驅動環境的系統。JMS 是一個用於開發和集成企業應用程式的重要的工具。因為許多公司都有以前遺留下來的系統和新近開發的系統綜合起來的情況,訊息的使用是整合整個企業的重要步驟。