首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

J2EE 1.4 消息規範變更詳解:JMS 1.1、MDB 2.1 與消息目標新機制

     編輯:Java 相關知識

J2EE 1.4 引入重大消息領域更新:統一 JMS 1.1 API、收緊容器使用限制、引入 message-destination 解耦生產消費配置、重構 MDB 部署描述符以支持非 JMS 協議。本文為遷移現有應用或新建項目提供完整參考。

一、 JMS 1.1:統一消息域 API

核心變化:Queue (PTP) 與 Topic (Pub/Sub) 接口統一為 ConnectionFactory、Destination、Connection、Session、MessageProducer、MessageConsumer。完全向後兼容,舊代碼無需修改;新代碼強烈建議僅使用統一接口。

統一 API 示例

InitialContext ctx = new InitialContext();
ConnectionFactory cf = (ConnectionFactory) ctx.lookup("java:comp/env/jms/cf");
Destination src = (Destination) ctx.lookup("java:comp/env/jms/source");
Connection conn = cf.createConnection();
conn.start();
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer consumer = sess.createConsumer(src);
Message msg = consumer.receive();
conn.close();

實際收益

  • 單一事務 Session 可同時 從 Queue 接收、向 Topic 發送 (或反向),無需 Bean/容器事務輔助。
  • 編程模型簡化,學習曲線降低。

二、 J2EE 容器對 JMS 使用的強制限制

1. 禁止使用的介面 (Application Server Facilities 專用)

  • javax.jms.ServerSession
  • javax.jms.ServerSessionPool
  • javax.jms.ConnectionConsumer
  • 所有 javax.jms.XA* 介面

2. 禁止在 Web/EJB 容器調用的方法 (明確限制於 Client Container)

Session.run()
QueueConnection.createConnectionConsumer()
TopicConnection.createConnectionConsumer()
TopicConnection.createDurableConnectionConsumer()
MessageConsumer.setMessageListener() / getMessageListener()
Connection.setExceptionListener() / stop() / setClientID()

關鍵影響:不能在 Servlet/EJB 中註冊 MessageListener (異步回調)。原因:JMS Provider 回調線程無容器上下文 (事務、安全 Principal)。替代方案:同步 receive() 輪詢、或改用 Message-Driven Bean (MDB) 由容器管理監聽。

3. 新限制:每個 Connection 僅允許一個活躍 Session

  • 調用 createSession() 後,必須 close() 原 Session 才能再次創建,否則拋異常。
  • 設計動機:配合 JCA 資源適配器模型——JCA 中 Connection 對應事務邊界,JMS 中 Session 對應事務;限制單 Session 使 JMS 更易實現為 JCA RA。
  • 開發調整:別再靜態緩存 Connection 並多線程共享多 Session。改為:EJB 實例變量緩存 Connection,確保單 Session;或每次用完即 close() (容器連接池使開銷可接受)。

三、 Message-Destination:解耦生產者與消費者配置

痛點:J2EE 1.3 用 resource-env-ref 定義目標,生產者查 jms/target,消費者查 jms/source,部署描述符無機制表達「它們綁定同一物理 Queue」。

J2EE 1.4 新元素

  • message-destination-ref:替代 resource-env-ref,新增兩子元素:
    • message-destination-usage:Produces / Consumes / ProducesConsumes —— 聲明用途,部署員據此配對。
    • message-destination-link:邏輯名,關聯到組裝描述符中的 message-destination。
  • message-destination (在 <assembly-descriptor> 中):邏輯目標定義,部署員將其綁定到物理 JMS Queue/Topic。

對比示例

J2EE 1.3 (雙 ref,部署員靠文檔/口頭協調綁定同一 Queue)

<resource-env-ref><resource-env-ref-name>jms/target</...><resource-env-ref-type>javax.jms.Queue</...></resource-env-ref>  // Sender
<resource-env-ref><resource-env-ref-name>jms/source</...><resource-env-ref-type>javax.jms.Queue</...></resource-env-ref>  // Receiver

J2EE 1.4 (單一 message-destination,意圖顯式)

<message-destination-ref>  // Sender
  <message-destination-ref-name>jms/target</...>
  <message-destination-type>javax.jms.Queue</...>
  <message-destination-usage>Produces</...>
  <message-destination-link>destination</...>
</message-destination-ref>

<message-destination-ref>  // Receiver
  <message-destination-ref-name>jms/source</...>
  <message-destination-type>javax.jms.Queue</...>
  <message-destination-usage>Consumes</...>
  <message-destination-link>destination</...>
</message-destination-ref>

<assembly-descriptor>
  <message-destination><message-destination-name>destination</...></message-destination>
</assembly-descriptor>

部署員僅需一個綁定:將 destination 映射到物理 Queue。支持跨 JAR 模塊鏈接 (../other/other.jar#destination)。

四、 Message-Driven Bean (MDB) 重大變更 (EJB 2.1)

1. 不再強制實現 javax.jms.MessageListener

新增 <messaging-type> 元素聲明實現接口 (如 javax.jms.MessageListener),為未來非 JMS 協議 (如 JCA 入站) 鋪路。現有 JMS MDB 代碼無需改動。

2. 部署描述符屬性標準化為 activation-config 名值對

EJB 2.0 專用元素EJB 2.1 activation-config-property-name (建議值)
<acknowledge-mode>acknowledgeMode (Auto-acknowledge / Dups-ok-acknowledge)
<destination-type>destinationType (javax.jms.Queue / javax.jms.Topic)
<subscription-durability>subscriptionDurability (NonDurable / Durable)
<message-selector>messageSelector (String 選擇器)

機制:JMS Provider 提供 ActivationSpec JavaBean,屬性即上述名稱。部署描述符中的值覆蓋管理員默認值。屬性僅為建議,具體以 Provider 文檔為準。

3. 支持 message-destination-link 直接綁定目標

<message-driven>
  <message-destination-type>javax.jms.Queue</...>
  <message-destination-link>destination</...>  <!-- 直接關聯 assembly-descriptor 中的邏輯目標 -->
  <activation-config>...</activation-config>
</message-driven>

運行時容器解析 Link → 物理 Destination 對象 → 注入 ActivationSpec.destination (若 Provider 支持 javax.jms.Destination 類型屬性)。

五、 遷移檢查清單

  1. 新代碼全面使用統一 JMS 1.1 API。
  2. 檢查 Servlet/EJB 是否調用被禁方法 (setMessageListener 等) → 改同步 receive() 或遷移至 MDB。
  3. 檢查是否單 Connection 多 Session 並發 → 重構為單 Session 或多 Connection。
  4. 將 resource-env-ref 遷移為 message-destination-ref + message-destination。
  5. 更新 MDB 部署描述符:加 messaging-type、用 activation-config 替換舊屬性、可選加 message-destination-link。
  6. 驗證 Provider ActivationSpec 支持哪些屬性名/值。

結語

J2EE 1.4 消息更新雖帶來遷移工作,但統一 API、解耦配置、MDB 協議中立化,奠定了現代 Java 消息開發基石。掌握上述變化,能平滑遷移並發揮新特性優勢。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved