CXF 2.2.3+ 支持 JMS 作為 SOAP 傳輸綁定,但官方示例不全。本文提供**完整可運行**的 Spring XML 配置,基於 ActiveMQ 嵌入式 Broker 驗證。
<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>
<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>
<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>
// 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 |
CXF + JMS 實現了**服務解耦、異步處理、削峰填谷**,配合 Spring XML 聲明式配置,開發體驗極佳。掌握 `JMSConfigFeature`、`JMSConfiguration`、連接工廠鏈三大核心組件協作關係,即可從容應對企業級異步服務架構落地。