程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 使用GlassFish實現JMS消息傳遞

使用GlassFish實現JMS消息傳遞

編輯:關於JAVA

對於當今的電子商務來說,在分布式異構系統之間進行通信已經成為不可避免的需求。現在,隨著 Java 消息服務 (JMS) 等消息標准的出現,開發松散耦合的同步或異步通信分布式系統(用於交換商務數 據和事件)已經非常簡單。

本文主要介紹如何使用 JMS 和消息驅動 Beans( Message-Driven Beans ,MDB )進行消息傳遞,特 別是企業消息傳遞的詳細信息。本文還將介紹 GlassFish 應用程序服務器的消息傳遞功能及其配置設置 。為了更好地說明這些技術,在此還將討論一個簡單的實時應用案例及其實施細節。

消息傳遞

簡單地說,消息傳遞是在雙方間發生的通信。企業消息傳遞可以定義為兩個軟件組件或兩個應用程序 之間的通信。消息傳遞就像發送物理信件一樣簡單,信件發送者准備好消息、給出正確的郵寄地址,然後 選擇正確的郵寄服務。在企業消息傳遞中也要有一個以特定格式向目的地發送消息的消息發送者。目的地 是面向消息的中間件或者是幫助交換消息的消息隊列。而且還要有從目的地同步或異步接收消息的消息用 戶。並不強制規定發送者和接受者在同樣的時間在線,也不強制規定他們必須相互認識才能交換信息。

消息傳遞系統的關鍵好處是保持分布式系統松懈地耦合。 松懈耦合使消息傳遞解決方案不同於其他的 緊密耦合通信解決方案(例如,遠程方法調用 (Remote Method Invocation,RMI)、公共對象請求代理 體系結構(Common Object Request Broker Architecture,CORBA)等等)。

JMS 消息傳遞

Java 消息服務( Java Messaging Service )是一個建立在 Java 2 平台企業版本 ( Java 2 Platform, Enterprise Edition,Java EE )之上的消息傳遞 API。它定義了一組創建、發送和接收消息 常用接口。

JMS 支持兩種消息傳遞模式:

點到點( PTP )模式

發布-訂閱模式

點到點消息傳遞模式依賴於消息隊列概念,也就是,將其中的消息地址寫到稱作隊列 的特定目的地。 接受者從隊列中使用消息,對其進行處理,然後確認收到消息。點到點消息傳遞模式的主要特征有:

每條消息有一個使用者。

在發送者和接收者之間沒有時間依賴性。

在發布-訂閱模式中,消息地址被寫到一個稱作主題 的目的地。消息生成器發布消息,使用者訂閱消 息。這種消息傳遞模式的主要特征有:

每條消息有多個使用者。

在發送者和接受者之間存在時間依賴性,也就是,使用者必須積極接受消息。即使訂閱者暫停使用, JMS API 也允許訂閱者創建持久訂閱方式 來接收消息。使用持久訂閱方式,JMS 提供器一直保留訂閱的 消息直到收到取消訂閱的請求或訂閱過期。

消息類型

JMS 支持 5 種消息類型:

文本: 一條簡單的文本消息或一個 java.lang.String 對象。

對象: Serializable(可序列化) Java 對象。

字節: 簡單的字節流。

映射表: 一組名稱 —— 值對集合。

數據流: 原始值數據流。

消息驅動 Beans(Message-Driven Beans,MDB)

消息驅動 bean 的工作是幫助異步處理消息。MDB 擔任 JMS 消息的偵聽器。JMS 客戶機不能找到 MDB 並直接調用方法;相反,客戶機將消息發送到 MDB 正在偵聽的目的地。當接收到消息時,EJB 容器調用 MDB 的onMessage 方法。這種方法通常將消息轉換為 5 種 JMS 消息類型中的 1 種,並作為應用程序的 業務邏輯進行處理。MDB 以異步模式運行,並且是無狀態、事務感知的。這些功能使 MDB 更具較高的伸 縮性,為企業發送消息提供了健壯的解決方案。

GlassFish 中的 JMS 支持

GlassFish 是開發和部署 Java EE 應用程序和 web 服務的開源應用程序服務器。該服務器與 Java Enterprise Edition 5 ( Java EE 5 ) 兼容,實際上是 Java EE 5 的參考實現。

GlassFish 通過提供一個完全集成的 JMS 提供器為 JMS 消息傳遞提供巨大支持。Java Message Service API 通過將 Sun Java System Message Queue 軟件集成到 GlassFish,並提供透明的 JMS 消息 傳遞支持得以實現。

GlassFish 支持兩種 JMS 資源: 連接工廠和目的地資源。

連接工廠是一種由 JMS 客戶機使用用於創建 JMS 提供器連接的對象。連接工廠有 3 種類型:

連接工廠: 由點到點以及發布 —— 訂閱消息傳遞模式使用。

隊列連接工廠: 由點到點消息傳遞模式使用。

主題連接工廠: 由發布 —— 訂閱消息傳遞模式使用。

目的地是一個對象,JMS 消息生成器使用這個對象以便將消息郵寄到該對象;它也是一種資源,JMS 消息使用者使用來自該資源的消息。支持目的地的類型有:

隊列: 隊列是點到點通信的目的地。

主題: 主題是發布 —— 訂閱通信的目的地。

下列內容是 GlassFish 支持的一些 JMS 連接功能。

連接池

GlassFish 服務器自動匯集 JMS 連接。用戶可以使用 GlassFish 管理控制台或 asadmin 命令設置連 接池屬性。在創建連接工廠時配置連接池細節。由 GlassFish 支持的一些連接池參數有:

連接池的初始值和最小值: 在連接池中指示初始連接的數量。這也是給連接池設置的最小連接數量。

連接池最大值: 在連接池中指示可用連接的最大數量。

連接池重新調整的數量: 當連接池達到空閒超時時,應該移除的連接數量。

空閒超時: 在連接池中連接可以保持空閒的最長時間。

最大等待

注釋

在 Java SE 5.0 中介紹過注釋,它是編程的聲明性樣式。注釋與元標記一樣,可以應用於類、構造函 數、方法、變量等等。

注釋 @Resource 用於查找連接工廠和目的地。在 Web 應用程序中,如果注釋放在變量上,那麼 servlet 容器將注入請求的資源;也就是,注釋變量將在為請求提供服務之前使用適當的值進行預先填充 。

@Resource(name="connFactory", mappedName="webTrackerConnFactory")
private QueueConnectionFactory qFactory;
@Resource(name="jmsQueue", mappedName="webTrackerQueue")
private Queue queue;

使消息傳遞正常運行

迄今為止,我們已經討論了如何將 JMS 和 MDB 一起運行來實施異步消息傳遞。我們也了解了 GlassFish 的功能和它提供的 JMS 支持。現在,我們將了解如何在稱作 “Web Access Tracker”的實時 應用案例的幫助下發揮這些技術的作用。

Web Access Tracker 幫助站點管理員或商務使用者監測用戶請求統計,例如一天的訪問數量、經常訪 問的頁面、頁面/服務請求時間、要求服務的時間等等。在下一部分我將解釋一個解決方案,在不破壞實 際應用程序性能的情況下收集被用戶訪問的每個網頁的訪問信息。您可以在參考資料部分的鏈接中下載該 樣例的完整資源代碼,以及它的可部署二進制文件。

解決方案

在其他技術(例如 Java XML 綁定架構 、 Java Server Faces (JSF)、 servlet 篩選器等等)的幫 助下,選擇基於 JMS 的消息傳遞解決方案捕獲和處理 web 訪問數據。GlassFish 為 JMS 消息傳遞以及 部署應用程序提供了支持。

演示應用程序使用 servlet 篩選器截取用戶請求並從請求消息標題中提取所需信息。然後,該信息將 作為 JMS 消息郵寄給消息隊列。消息通過消息驅動 bean 這一 JMS 消息使用者異步傳遞。從消息中收集 的數據將被永久保留到 XML 數據存儲區中。JAXB 是用於訪問和將數據存儲到 XML 文件的首選技術。使 用 JSF 開發用戶界面。

系統需求

Java EE 5

GlassFish 應用程序服務器

其他庫文件: Apache 服務器的 commons-beanutils.jar、 commons-collections.jar 和 commons- logging.jar 文件

Servlet 篩選器

servlet 篩選器或者篩選向資源發出的請求,或者篩選從資源中發出的響應,或者對兩者同時執行篩 選任務。您可以通過實施 Filter 界面書寫自己的篩選器。該界面中的主要方法是執行核心篩選行為的 doFilter 方法。您還可以在篩選類中實施 初始化和 銷毀 方法。這些方法由 servlet 容器調用用於初 始化和銷毀篩選器。

樣例應用程序使用稱作 WebTrackerFilter 的 servlet 篩選器捕獲屬於請求的信息;也就是,被請求 頁面的 URL 、主機 IP、請求時間等等。從請求收集的信息將作為數據傳輸對象( Data Transfer Object,DTO )發送給消息分發器做進一步處理。

public void doFilter(ServletRequest request,
     ServletResponse response, FilterChain chain)
     throws java.io.IOException, ServletException {
   HttpServletRequest httpServletRequest = (HttpServletRequest)
               request;
   HttpServletResponse httpServletResponse = (HttpServletResponse)
               response;

   // Extract required header parameters and set it in DTO
   RequestData data = new RequestData();
   data.setQueryString(request.getQueryString());
   data.setRemoteAddress(request.getRemoteAddr());
   data.setRequestURI(request.getRequestURI());
   data.setResponseTime(elapsedTime);
   data.setUserAgent(request.getHeader("User-Agent"));
   // send the data to message dispatcher
   messagedispatcher.sendRequestData(data);
   chain.doFilter(httpServletRequest, httpServletResponse);
}

配置 Servlet 篩選器

我們已經了解如何編寫自定義篩選器程序,那麼現在我們需要在 web 應用程序部署的描述符中配置 篩選器類;也就是 web.xml 文件。篩選器類可以在部署描述符文件中通過添加 <filter> 元素 進行配置。該元素創建篩選器的名稱以及篩選器實現類的名稱。使用 <filter-mapping> 元素可以 將 servlet/URL 模式映射到篩選器中。這將導致 WebTrackerFilter 被 URL 模式為 *.html 的所有請求 調用。下列元素顯示如何配置 WebTrackerFilter。

<filter>
   <filter-name>WebTrackerFilter</filter-name>
   <filter-class>demo.webtracker.filter.WebTrackerFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>WebTrackerFilter</filter-name>
    <url-pattern>*.html</url-pattern>
</filter-mapping>

異步消息傳遞

使用 WebTrackerFilter 可獲得請求信息;下一步是開發 JMS 客戶機以 JMS 消息的形式將數據郵寄 到消息隊列。選擇點到點模式進行消息傳遞。

為典型 JMS 客戶機開發的代碼片斷如下所示。您需要使用從 JNDI 樹中檢索到的 JMS 管理對象 InitialContext,執行連接工廠和目的地的 JNDI 查找操作。另一種選擇是,在運行時使用注釋來注入 JMS 資源。在代碼中使用的 webTrackerConnFactory 和 webTrackerQueue 分別是連接工廠和目的地的 JNDI 名稱。客戶機假設這些資源已經在 GlassFish 中進行了配置,那麼配置需要在執行這些代碼之前完 成。參考 “在 GlassFish 中配置 JMS 資源” 部分來了解如何在 GlassFish 中配置 JMS 資源。

在連接工廠上使用 createQueueConnection 方法,可以創建一個到 JMS 服務提供器的 Connection( 連接)。連接提供對基礎消息傳輸的訪問。

接下來的任務是使用 createSession 方法在 Connection 對象上創建 JMS Session(會話)。會話是 生成和使用消息的單線程上下文。createSession 的第一個參數決定是否執行 JMS 會話,第二個參數指 示消息確認模式。在本樣例中,不執行會話,而是在接受消息時自動確認會話。

您還有必要創建一個用於將消息發送到目的地的 MessageProducer。最後一步是創建 JMS ObjectMessage 並設置請求數據為消息。然後將消息發送到消息隊列。

// Get queue connection factory
QueueConnectionFactory qFactory = (QueueConnectionFactory)jndi.
         lookup("webTrackerConnFactory");
// Get queue
Queue queue = (Queue)jndi.lookup("webTrackerQueue");
// Get queue connection
QueueConnection qConn = (QueueConnection)qFactory.
         createConnection();
// Get session
Session session = qConn.createSession(false,
       Session.AUTO_ACKNOWLEDGE);
// Set the JMS message
ObjectMessage msg = session.createObjectMessage();
msg.setObject(data);
// Send JMS message
session.createProducer(jmsLoc.getMessageQueue()).send(msg);

消息驅動 Beans

消息驅動 bean 將作為 JMS 消息的偵聽器。當消息到達隊列時,容器調用 MDB 的 onMessage() 方法 。該方法將消息轉換為數據原始消息類型(也就是,ObjectMessage ),然後進行格式化並永久保存到數據 存儲區。MDB 實現 MessageDrivenBean 界面和消息類型支持的 MessageListener 界面(可選);也就是 ,如果 bean 支持 JMS,javax.jms.MessageListener將是要實現的界面。

下面給出了接收 JMS 消息的代碼:

public void onMessage(Message message) {    
   if (message instanceof ObjectMessage) {
    RequestData data = (RequestData)((ObjectMessage)message).
              getObject();
    // persist data
   }
}

如果您正在使用 Java EE 5,MDB 可以使用 @MessageDriven 注釋進行注釋。該注釋包含一個 mappedName 元素,該元素指定 bean 將要偵聽的消息隊列的 JNDI 名稱 。MDB 可以使用 @Resource 注 釋注入 MessageDrivenContext 資源。在這種情況下,您不必聲明 EJB 部署描述符的 bean 細節。MDB 的最前面幾行如下所示:

@MessageDriven(mappedName = "webTrackerQueue")
public class WebTrackerEJB implements MessageListener {
/** Context for the MDB. */
@Resource
private MessageDrivenContext mdbContext;
.........

Java XML 綁定架構(JAXB)

從用戶請求中捕獲的數據可以永久存儲到數據存儲區。出於簡單,在本樣例中 XML 數據存儲區已經選 定。JAXB 是解編和編組 XML 文檔的首選技術。JAXB 提供了一種方便途徑,通過將 XML 模式綁定到 Java 表示並使用 Java 對象訪問和處理 XML 內容。XML 的 Java 對象表示可以按照下列步驟創建:

准備數據存儲區的 XML 結構。

創建 XML 模式定義(XML Schema Definition,XSD)。參考在 webtracker-src/config 目錄中提供 的 webAccess-sample.xml 和 webAccess.xsd 文件,尋找在本樣例中使用的關於 XML 數據存儲區和模式 定義的更多細節。

使用 JAXB 的 XJC 命令來生成提供 XSD 所需的 Java 文件。在 <GlassFish_Root>/bin 目錄 中包含 XJC.bat 文件。

XML 文檔解編

數據解編是從 XML 文檔中創建對象樹的過程。要解編 XML 文檔,您需要創建 JAXBContext。 JAXBContext 提供管理 XML/Java 綁定信息的抽象。含有模式派生類的 Java 包應作為一個參數傳遞,以 便創建 JAXBContext。使用 JAXBContext 創建的 XML 解組器可用於檢索 XML 文檔的根元素。

解編 XML 數據文件的代碼如下所示:

// create a JAXBContext
JAXBContext jc = JAXBContext.newInstance
       ("demo.webtracker.xmlgen");
// create UnMarshaller
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement rootElement = (JAXBElement)unmarshaller.unmarshal
       (new FileInputStream(xmlDataStorePath));
// Get the root element
WebAccess access = (WebAccess)rootElement.getValue();

XML 文檔編組

編組過程是從內容樹中創建 XML 文檔。要編組 XML 文檔,您需要創建 JAXBContext。

編組 XML 數據文件的代碼如下所示:

// create a JAXBContext
JAXBContext jc = JAXBContext.newInstance
       ("demo.webtracker.xmlgen");
// create a Marshaller and marshal to webAccessLog.xml
Marshaller marshaller = jc.createMarshaller();
// Converts java object to XML data
marshaller.marshal(accessData, new File(xmlDataStorePath));

在 GlassFish 中配 置 JMS 資源

如果 JMS 客戶機要向目的地發送消息,連接工廠和目的地的資源需要在 GlassFish 中進行配置。這 些資源可以通過 GlassFish 的管理控制台創建,也可以通過 asadmin 命令創建。

創建 JMS 連接工廠

JMS 連接工廠允許應用程序以編程方式創建其他 JMS 對象。使用管理控制台按照下列步驟配置連接工 廠:

登錄 GlassFish 管理控制台。

從左側的導航條展開 Resources -> JMSResources 菜單。

選擇 Connection Factories 節點。

單擊 New 按鈕創建一個新的連接工廠。

輸入下列內容:

將 “webTrackerConnFactory” 作為 JNDI Name(JNDI 名稱)。這是連接工廠的惟一 JNDI 名稱。 JMS 客戶機使用該名稱查找連接工廠。JNDI 名稱可以多達 255 個字符,而且必須只包含字母數字、下劃 線、破折號、或點號字符。

將“javax.jms.QueueConnectionFactory”作為 Resource Type(資源類型)。在樣例應用程序中, 我們已經選擇了點到點消息傳遞模式,因此資源類型應該是 QueueConnectionFactory。

將 “Webtracker Connection Factory”作為 Description (描述)名稱。

單擊 OK 按鈕。

創建 JMS 消息隊列

JMS 目的地作為消息的存儲庫。使用管理控制台按照下列步驟配置連接工廠:

登錄 GlassFish 管理控制台。

從左側的導航條展開 Resources -> JMSResources 菜單。

選擇 Destination Resources。

單擊 New 按鈕以便創建目的地。

輸入下列內容:

將 “webTrackerQueue” 作為 JNDI Name(JNDI 名稱)。這是目的地的惟一 JNDI 名稱。JMS 客戶 機使用該名稱查找消息隊列。

將 “webTrackerQueue” 作為物理目的地。這是在消息代理中的目的地名稱。

將“javax.jms.Queue”作為 Resource Type。由於我們采用點到點模式,資源類型應該是 Queue(隊 列)。

將 “Webtracker Queue Destination”作為 Description(描述)名稱。

單擊 OK 按鈕。

在 GlassFish 中部署應用程序

將應用程序打包,作為由 web 模塊和 EJB 模塊組成的企業應用歸檔(enterprise application archive,EAR )文件。web 模塊處理應用程序的用戶界面。將消息驅動 bean 和其他數據訪問類打包作 為 EJB 模塊。下列步驟解釋了在 GlassFish 中樣例應用程序的部署。

登錄 GlassFish 管理控制台。

從左側的導航條選擇 Applications -> Enterprise Applications。

單擊 Deploy 按鈕以便部署 webtracker 應用程序。

浏覽 webTracker.ear 文件並上傳它。

單擊 OK 按鈕。

將 webtracker-src/config 中提供的 webAccess.xml 文件復制到任意本地目錄下。添加稱作 xmlstore.path 的系統屬性,並將它指向該目錄。您可以從 GlassFish 管理控制台中選擇 Application Server -> JVM Settings -> JVM Options -> Add JVM Option 設置系統屬性。樣例條目為 - Dxmlstore.path=C:/temp/webAccessLog.xml。

部署描述符ejb-jar.xml

用於樣例應用程序的 ejb-jar.xml 部署描述符如下所示: 您必須將 WebTrackerEJB 聲明為消息驅動 bean 並將 javax.jms.Queue 作為消息目的地的類型。如果您已經在 Java EE 5 中注釋了 MDB,那麼可 以忽略該配置。

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
  <display-name>Web Tracker App</display-name>
  <enterprise-beans>
   <message-driven>
     <display-name>WebTrackerEJB</display-name>
     <ejb-name>WebTrackerEJB</ejb-name>
     <ejb-class>demo.webtracker.ejb.WebTrackerEJB</ejb-class>
    <transaction-type>Container</transaction-type>
     <message-destination-type>
     javax.jms.Queue
    </message-destination-type>
   </message-driven>
  </enterprise-beans>
  <assembly-descriptor>
   <container-transaction>
     <method>
      <ejb-name>WebTrackerEJB</ejb-name>
      <method-name>*</method-name>
     </method>
      <trans-attribute>Required</trans-attribute>
    </container-transaction>
  </assembly-descriptor>
</ejb-jar>

sun-ejb-jar.xml

用於樣例應用程序的 sun-ejb-jar.xml 部署描述符如下所示: 連接工廠和隊列的 JNDI 名稱將在描 述符中聲明。如果您已經在 Java EE 5 中注釋了 MDB,那麼可以忽略該配置。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-ejb-jar PUBLIC "-//Sun Microsystems, Inc.
//DTD Application Server 9.0 EJB 3.0//EN"
"http://www.sun.com/software/appserver/dtds/sun-ejb-jar_3_0-0.dtd">
<sun-ejb-jar>
  <enterprise-beans>
   <ejb>
    <ejb-name>WebTrackerEJB</ejb-name>
    <jndi-name>webTrackerQueue</jndi-name>
    <mdb-connection-factory>
      <jndi-name>webTrackerConnFactory</jndi-name>
    </mdb-connection-factory>
   </ejb>
  </enterprise-beans>
</sun-ejb-jar>

測試應用程序

現在已經成功部署了應用程序,准備進行測試。可以使用下列 URL 訪問應用程序的主頁:

http://<host name>:<port number>/webTracker

圖 1 顯示了主頁的快照。

圖 1. Web Access Tracker 的主頁

web 訪問報告可以通過單擊在左側導航條提供的 Web Access Info 鏈接查看。在圖 2 中顯示該報告 。

圖 2. Web 訪問報告

結束語

在本文中我們探索了 JMS 消息傳遞和 GlassFish 的消息傳遞功能。毫無疑問,JMS 已經贏得了廣泛 的行業支持並成為功能強大的企業消息傳遞解決方案。在本文中解釋的應用案例,真正地演示了 JMS 使 用消息傳遞解決方案解決實時問題的美妙之處。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved