程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2EE >> 全面研讀 EJB 2.0(下)

全面研讀 EJB 2.0(下)

編輯:J2EE
MessageDrivenBean   在 EJB 2.0 中,對規范的一個基礎性更改是添加了一種全新的企業級 bean 類型,即 MessageDrivenBean。MessageDrivenBean 專門設計來處理入網的 JMS 消息。對於許多開發人員來說,JMS 是一種新的范例,所以本文將花一些時間逐步說明對 JMS 的理解,以及它們在 EJB 2.0 中的用法。   什麼是 JMS?   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 客戶機可以發送消息而不必等待回應。比較可知,這完全不同於基於 RPC 的(基於遠程過程的)系統,如 EJB 1.1、CORBA 和 Java RMI 的引用實現。在 RPC 中,客戶機調用服務器上某個分布式對象的一個方法。在方法調用返回之前,該客戶機被阻塞;該客戶機在可以執行下一條指令之前,必須等待方法調用結束。在 JMS 中,客戶機將消息發送給一個虛擬通道(主題或隊列),而其它 JMS 客戶機則預訂或監聽這個虛擬通道。當 JMS 客戶機發送消息時,它並不等待回應。它執行發送操作,然後繼續執行下一條指令。消息可能最終轉發到一個或許多個客戶機,這些客戶機都不需要作出回應。   EJB 2.0 中的 JMS   EJB 2.0 以兩種方式支持 JMS 的集成:作為一種 bean 可用的資源,和作為一個 MessageDrivenBean。當將 JMS 用作一種資源時,使用 JMS API 的 bean 就是消息的產生者或發送者。在這種情況下,bean 將消息發送給稱為主題或隊列的虛擬通道。另一方面,MessageDrivenBean 則是消息的使用者或接收者。它監聽特定的虛擬通道(主題或隊列),並處理發送給該通道的消息。為了更好地理解消息產生者和消息使用者的作用,用 SessionBean bean 來發送一條使用 JMS 的消息,然後使用一個新的 MessageDrivenBean 來使用該同一條消息。   作為 EJB 2.0 資源的 JMS   會話 bean 和實體 bean 都是基於 RPC 的組件,為了將各種事務性的組件裝配到一起,這是一種卓越的體系結構。但是,在某些情況下,RPC 的同步性質會成為一種障礙,這正是 EJB 1.1 中將對 JMS API 的訪問作為一種資源包括在內的原因。利用 JNDI 環境命名的上下文,bean 可以獲得一個 JMS 工廠,並將一條異步消息發送給主題或隊列(也從 JNDI 獲得),而不必等待回應。下面是 ShoppingCart bean 的一個例子,它使用 JMS 將 Order 的詳細信息發送給消息收發主題。   public class ShoppingCartBean implements SessionBean {    // 訂單詳細信息是一個可序列化的對象,它包含全部訂單信息。    public OrderDetail orderDetail;    public void processOrder(){     // 處理訂單的邏輯從此處開始     ....     // ... 處理訂單以後,向其它系統發送有關此訂單的一條消息     InitialContext jndiEnc = new     InitialContext();     // 使用 JNDI ENC 獲取 JMS 工廠和主題標識符     TopicConnectionFactory factory =     jndiEnc.lookup("java:comp/env/jms/topicfactory");     Topic orderTopic =     jndIEnc.lookup("java:comp/env/jms/ordertopic");     // 獲得一個用來發送消息的發布者     TopicConnection con = factory.createTopicConnection();     TopicSession session = con.createTopicSession(false, Session.AUTO_ACKNOWLEDGE );     TopicPublisher publisher = session.createPublisher(orderTopic);     // 將一個 ObjectMessage 發送給主題(虛擬通道)     bjectMessage message = session.createObjectMessage();     message.setObject(orderDetail);     publisher.publish(message);     con.close();    }   ...   } 在這種情況下,JMS 是用來通知另外的應用程序,訂單已被處理。這些另外的應用程序對於處理訂單來說並不重要,但它們會因為得到一個訂單已被處理的通知而受益。這樣的例子包括自動調整庫存的庫存系統,和能將客戶添加進產品目錄郵寄名單中的銷售應用程序。   使用 JMS 使 bean 能夠發布(發送)消息而不會發生阻塞。bean 並不知道誰將收到消息,因為它是將消息發送給某個主題(虛擬通道),而不是直接發送給另一個應用程序。應用程序可以選擇預訂該主題,並接收有關新訂單的通知。這樣就有可能動態地在虛擬通道中添加或刪除應用程序,從而產生了一種更加靈活的系統。   預訂了訂單主題的應用程序將收到有關新訂單的通知,應用程序可以使用它們認為合適的任何方式來處理這個通知。預訂了各種主題的應用程序或者從各個隊列中接收消息的應用程序可以是 Java 應用程序、EAI 系統(用於集成遺留系統和 ERP 系統)或者 MessageDrivenBean 組件,在 JMS 的術語中,它們全部被認為是 JMS 客戶機。 JMS 和 MessageDrivenBean   雖然大多數 JMS 廠商都提供消息中介工具,來將消息從發送者路由到接收者,但構建使用(接收)消息的 JMS 客戶機卻是應用程序開發人員的職責。在許多情況下,接收消息的應用程序必須強健、安全、快速而且可伸縮;它需要的基礎結構基本上與 EJB 應用程序相同。   由於認識到這種需要,EJB 2.0 現在包括了 MessageDrivenBean 類型,它可以使用 JMS 消息,並且在同一個強健的、基於組件的基礎結構中處理這些消息,這樣的基礎結構對於會話 bean 和實體 bean 都非常有用。MessageDrivenBean 類型(消息 bean)是一種企業級 bean 組件,它設計來使用異步的 JMS 消息。   除了提供容器基礎結構以外,EJB 還具有另一個重要的優點:並發處理。在 EJB 中,一個已部署的消息 bean 表示一個單一的消息使用者,但這個 bean 本身是由許多 bean 實例提供服務的。每個 bean 實例都可以分別地使用消息 bean 接收到的消息。這意味著,消息 bean 不必像常規 JMS 客戶機那樣連續地使用消息。消息 bean 可以並發地使用接收到的多個消息,這樣就能達到比傳統 JMS 應用程序高得多吞吐量和好得多的可伸縮性。   為了說明消息 bean 的作用,就開發了 MarketingBean 類,並將它從訂單主題中部署到供使用的消息中去。MarketingBean 將從消息中提取 OrderDetail 對象,並使用它將客戶添加到適當的目錄郵寄名單中。這是一種最精致的大量郵寄系統。   下面是 MarketingBean 類的定義,這個類使用發布給訂單主題的消息。   public class MarketingBean implements     javax.ejb.MessageDrivenBean {      public void onMessage(Message message) {       ObjectMessage orderMessage = (ObjectMessage)orderMessage:       OrderDetail orderDetail = (OrderDetail)orderMessage.getObject();       Integer customerID = orderDetail.getCustomerID();       InitialContext jndiEnc = new InitialContext();       CatalogHome catalogHome = (CatalogHome)jndIEnc.lookup("java:comp/env/ejb/catalog");       Iterator productIDs = orderDetail.getProductsIDs();       while(productIDs.hasNext()){        Integer productID = (Integer)productIDs.next();        Catalog cat = CatalogHome.findByProductID(productID);        cat.addCustomerToMailingList(customerID);       }      }     } 正像會話 bean 和實體 bean 一樣,MessageDrivenBean 也是一種完備的企業級 bean,但其間仍存在一些重要的區別。消息 bean 沒有遠程接口或本地接口。這是因為消息 bean 不是 RPC 組件。它沒有供 EJB 客戶機調用的業務方法。消息 bean 監聽虛擬消息通道(主題或隊列),並使用其它 JMS 客戶機發送給該通道的消息。   各個消息 bean 構成一個 bean 類,這個類實現 MessageDrivenBean 接口和一個 XML 部署描述符。下面是 MessageDrivenBean 接口的定義,所有消息 bean 都必須實現這個接口。   package javax.ejb;   import javax.jms.Message;   import javax.jms.MessageListener;   public interface MessageDrivenBean extends    MessageListener{     public void onMessage(Message message);     public void ejbCreate();     public void ejbRemove();     public void      setMessageDrivenContext(MessageDrivenContext mdc);    } 當部署了一個消息驅動的 bean 以後,它就被指派來處理特定主題或隊列中的消息。JMS 客戶機(Java 應用程序、bean 或本地客戶機)發送的任何消息,將由消息路由器轉發給消息 bean,該消息 bean 正是被指派來從該虛擬通道中接收消息的。當一條消息被發送給一個消息 bean 時,EJB 容器就會從某個池中選擇該 bean 的一個實例,來處理這條消息。當 bean 實例調用其 onMessage() 方法時,它就會接收到這條消息,並能夠以它認為合適的任何方式來處理這條消息。一旦這條消息被使用,則只要事務沒有異常中止,這條消息都不會被傳送給這個消息 bean 的任何其它實例。   消息 bean 在某點上類似於無狀態的會話 bean,即這兩種 bean 在兩次請求之間都不保持任何狀態。因此,消息驅動的 bean 是無狀態的,但是,就像無狀態的會話 bean 一樣,它們也可以有實例變量,這些變量在這個 bean 實例的整個生存期內均保持。   對消息 bean 的最後一點說明是,理解這樣一個事實是很重要的,即 bean 使用的消息不一定要是由其它 bean 所產生的。消息 bean 可以使用由符合 JMS 的廠商提供的任何主題或隊列中的消息。消息 bean 使用的消息可以來自其它 bean(會話 bean、實體 bean 或消息 bean)、非 EJB 的 Java 應用程序、或者甚至非 Java 的應用程序(如果其供應商符合 JMS)。例如,遺留應用程序可能使用 IBM 的 MQSerIEs 向隊列發送消息,而該消息既可以由其它遺留應用程序使用,同樣可以由消息 bean 使用。   結論   與以前的規范相比,Enterprise JavaBeans 2.0 中作了一些相當大的更改。新的 CMP 模型比以前的模型要靈活得多,它允許各種實體為復雜的對象圖建立模型,而同又提供跨容器的更大的可移植性。人們迫切地期待著為查找和選擇操作定義一種通用的查詢語言,而它也將有助於提高可移植性。   這種新的 MessageDrivenBean 類型將有助於使這種強大的消息收發范例成為眾人矚目的焦點,就像 EJB 那樣。消息收發在分布式的混合計算中是一個極其重要的組成部分,將它包括在 EJB 內就是其重要性的一個證明。   在寫這篇文章時,EJB 2.0 剛剛作為公開草案發布,這意味著在它成為一個最終規范之前仍有可能更改。如果更改對此處提供的材料有重大影響,屆時我將設法對本文作一些注釋,但這個規范正在趨於穩定,所以不太可能有真正重大的更改。
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved