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

CXF 3.x 整合 JMS 傳輸全配置:Spring XML 方案與 ActiveMQ 嵌入式實戰

     編輯:Java 相關知識

背景:CXF 原生 JMS 傳輸配置稀缺,坑多文檔少

CXF 2.2.3+ 支持 JMS 作為 SOAP 傳輸綁定,但官方示例不全。本文提供**完整可運行**的 Spring XML 配置,基於 ActiveMQ 嵌入式 Broker 驗證。

核心依賴 (Maven)

<dependency>
  <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-rt-transports-jms</artifactId>
  <version>3.4.x</version> <!-- 對應 CXF 版本 -->
</dependency>
<dependency>
  <groupId>org.apache.activemq</groupId>
  <artifactId>activemq-broker</artifactId>
  <version>5.16.x</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jms</artifactId>
  <version>5.3.x</version>
</dependency>

服務端配置 (server-applicationContext.xml)

<beans xmlns="https://www.springframework.org/schema/beans"
       xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="https://www.springframework.org/schema/p"
       xmlns:jaxws="https://cxf.apache.org/jaxws"
       xsi:schemaLocation="
         https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
         https://cxf.apache.org/jaxws https://cxf.apache.org/schemas/jaxws.xsd">

  <!-- CXF 核心與 JMS 擴展 -->
  <import resource="classpath:META-INF/cxf/cxf.xml"/>
  <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
  <import resource="classpath:META-INF/cxf/cxf-extension-jms.xml"/>

  <!-- 發布端點:JMS 地址 -->
  <jaxws:endpoint
      xmlns:customer="https://customerservice.service.test/"
      id="CustomerService"
      address="jms://localhost:61616"
      serviceName="customer:CustomerServiceService"
      endpointName="customer:CustomerServiceEndpoint"
      implementor="test.service.impl.CustomerServiceImpl">

    <jaxws:features>
      <bean class="org.apache.cxf.transport.jms.JMSConfigFeature"
           p:jmsConfig-ref="jmsConfig"/>
    </jaxws:features>
  </jaxws:endpoint>

  <!-- JMS 配置核心 -->
  <bean id="jmsConfig"
        class="org.apache.cxf.transport.jms.JMSConfiguration"
        p:connectionFactory-ref="jmsConnectionFactory"
        p:targetDestination="test.cxf.jmstransport.queue"/>

  <!-- ActiveMQ 連接工廠 (單連接模式) -->
  <bean id="jmsConnectionFactory"
        class="org.springframework.jms.connection.SingleConnectionFactory">
    <property name="targetConnectionFactory">
      <bean class="org.apache.activemq.ActiveMQConnectionFactory"
            p:brokerURL="tcp://localhost:61616"/>
    </property>
  </bean>
</beans>

客戶端配置 (client-applicationContext.xml)

<beans ...>
  <import resource="classpath:META-INF/cxf/cxf.xml"/>
  <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
  <import resource="classpath:META-INF/cxf/cxf-extension-jms.xml"/>

  <jaxws:client
      id="CustomerService"
      xmlns:customer="https://customerservice.service.test/"
      serviceName="customer:CustomerServiceService"
      endpointName="customer:CustomerServiceEndpoint"
      address="jms://localhost:61616"
      serviceClass="test.service.CustomerService">

    <jaxws:features>
      <bean class="org.apache.cxf.transport.jms.JMSConfigFeature"
           p:jmsConfig-ref="jmsConfig"/>
    </jaxws:features>
  </jaxws:client>

  <bean id="jmsConfig"
        class="org.apache.cxf.transport.jms.JMSConfiguration"
        p:connectionFactory-ref="jmsConnectionFactory"
        p:targetDestination="test.cxf.jmstransport.queue"/>

  <bean id="jmsConnectionFactory"
        class="org.springframework.jms.connection.SingleConnectionFactory">
    <property name="targetConnectionFactory">
      <bean class="org.apache.activemq.ActiveMQConnectionFactory"
            p:brokerURL="tcp://localhost:61616"/>
    </property>
  </bean>
</beans>

啟動類與嵌入式 Broker

// Server
public class ServerApp {
    public static void main(String[] args) {
        new ClassPathXmlApplicationContext("server-applicationContext.xml");
    }
}

// Client
public class ClientApp {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("client-applicationContext.xml");
        CustomerService svc = ctx.getBean("CustomerService", CustomerService.class);
        System.out.println(svc.getOrder(null).getName());
    }
}

// Embedded Broker (測試用,生產用獨立 Broker)
public class EmbeddedBroker {
    public static void main(String[] args) throws Exception {
        BrokerService broker = new BrokerService();
        broker.setPersistenceAdapter(new MemoryPersistenceAdapter());
        broker.addConnector("tcp://localhost:61616");
        broker.start();
        System.out.println("JMS broker ready");
        Thread.sleep(Long.MAX_VALUE); // 持續運行
    }
}

關鍵配置解析

組件作用注意點
cxf-extension-jms.xml註冊 JMS 傳輸工廠、Conduit、Destination必須 import,否則 address="jms://" 無法識別
JMSConfigFeature將 JMSConfiguration 注入端點/客戶端p:jmsConfig-ref 引用同名 bean
JMSConfiguration.targetDestination指定隊列/主題名稱客戶端服務端必須一致
SingleConnectionFactory緩存單一連接,避免頻繁創建開銷生產高並發可改 CachingConnectionFactory
ActiveMQConnectionFactory.brokerURL指定 Broker 地址嵌入式/獨立均用 tcp://host:port

常見坑點與解決

  1. 缺少 cxf-extension-jms.xml:啟動報 `No transport factory for 'jms'` → 必須 import。
  2. 隊列名不一致:請求發出但服務端收不到 → 檢查 `targetDestination` 拼寫。
  3. 連接工廠未共享:客戶端每次調用新建連接極慢 → 必須用 `SingleConnectionFactory` 包裝。
  4. 事務與確認模式:默認 `AUTO_ACKNOWLEDGE`,需事務時配置 `jmsConfig.sessionTransacted=true` 並配置 Spring 事務管理器。
  5. 防火牆/網絡:Broker 端口 61616 需雙向通暢。

生產化建議

  • Broker 獨立部署 (ActiveMQ/Artemis/RabbitMQ),配置高可用集群。
  • 使用 `CachingConnectionFactory` + `sessionCacheSize` 優化連接池。
  • 啟用 JMS 消息持久化、死信隊列、監控指標 (JMX/Prometheus)。
  • 考慮 CXF 的 `JMSDestinationResolver` 實現動態隊列路由。

結語

CXF + JMS 實現了**服務解耦、異步處理、削峰填谷**,配合 Spring XML 聲明式配置,開發體驗極佳。掌握 `JMSConfigFeature`、`JMSConfiguration`、連接工廠鏈三大核心組件協作關係,即可從容應對企業級異步服務架構落地。

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