知識庫 / Spring RSS 訂閱

Spring 與 JMS 和 ActiveMQ 的遠程調用

Spring
HongKong
2
02:33 PM · Dec 06 ,2025

1. 概述

我們在上一篇文章中瞭解到,Spring Remoting 可以通過異步通道作為 AMQP 隊列,提供 RPC 服務。然而,我們也可以使用 JMS 達到相同的效果。

在本篇文章中,我們將探討如何使用 Spring Remoting JMSApache ActiveMQ 作為消息中間件進行遠程調用。

2. 啓動 Apache ActiveMQ 代理服務器

Apache ActiveMQ 是一款 開源消息代理,它允許應用程序異步交換信息,並且完全兼容 Java 消息服務 API

為了運行我們的實驗,我們首先需要設置一個運行的 ActiveMQ 實例。我們可以選擇以下幾種方式:按照 官方指南 中描述的步驟,將其嵌入到 Java 應用程序中,或者更簡單地使用以下命令啓動一個 Docker 容器:

docker run -p 61616:61616 -p 8161:8161 rmohr/activemq:5.14.3

這將啓動一個 ActiveMQ 容器,通過其暴露端口 8161 上的一個簡單的管理 Web GUI,通過它可以檢查可用的隊列、連接的客户端和其他管理信息。 JMS 客户端需要使用端口 61616 與代理服務器連接並交換消息。

3. Maven 依賴

如前幾篇文章介紹的 Spring Remoting 一樣,我們將設置一個服務器和一個客户端 Spring Boot 應用程序,以演示 JMS Remoting 的工作原理。

如常,我們會仔細選擇 Spring Boot starter 依賴項,正如此處所述:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-activemq</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>

我們明確排除了 spring-boot-starter-tomcat,以避免將 Tomcat 相關的文件放入類路徑中。

這反過來又將阻止 Spring Boot 的自動配置機制在應用程序啓動時啓動嵌入式 Web 服務器,因為我們不需要它。

4. 服務器應用程序

4.1. 暴露服務

我們將設置一個服務器應用程序,該應用程序會暴露 CabBookingService,客户端可以調用它。

第一步是聲明一個實現我們想要暴露給客户端接口的 Bean。 這是一個 Bean,它將在服務器端執行業務邏輯:

@Bean 
CabBookingService bookingService() {
    return new CabBookingServiceImpl();
}

我們接下來定義服務器從哪個隊列檢索調用實例,並在構造函數中指定其名稱:

@Bean 
Queue queue() {
    return new ActiveMQQueue("remotingQueue");
}

正如我們之前文章中所知,Spring Remoting 的主要概念之一是 Service Exporter,該組件負責收集來自某些源的調用請求,在本例中,是 ApacheMQ 隊列,並調用服務實現的所需方法。

為了與 JMS 配合使用,我們定義了 JmsInvokerServiceExporter

@Bean 
JmsInvokerServiceExporter exporter(CabBookingService implementation) {
    JmsInvokerServiceExporter exporter = new JmsInvokerServiceExporter();
    exporter.setServiceInterface(CabBookingService.class);
    exporter.setService(implementation);
    return exporter;
}

最後,我們需要定義一個監聽器,負責消費消息。該監聽器作為 ApacheMQ 和 JmsInvokerServiceExporter 之間的橋樑,它會監聽隊列中可用的調用消息,將調用轉發給服務導出器,並序列化返回結果:

@Bean SimpleMessageListenerContainer listener(
  ConnectionFactory factory, 
  JmsInvokerServiceExporter exporter) {
 
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setConnectionFactory(factory);
    container.setDestinationName("remotingQueue");
    container.setConcurrentConsumers(1);
    container.setMessageListener(exporter);
    return container;
}

4.2. 配置

請務必設置 application.properties 文件,以便 Spring Boot 可以配置一些基本對象,例如監聽器所需的 ConnectionFactory

各個參數的值主要取決於 ApacheMQ 的安裝方式,以下配置對於我們在同一台機器上運行這些示例的 Docker 容器來説是一個合理的配置:

spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.packages.trusted=org.springframework.remoting.support,java.lang,com.baeldung.api

spring.activemq.broker-url 參數是指 AMQ 端口的引用。spring.activemq.packages.trusted 參數需要更深入的解釋。

從版本 5.12.2 開始,ActiveMQ 默認拒絕所有類型為 ObjectMessage 的消息,因為這些消息被認為可能成為某些上下文中的安全攻擊媒介。

無論如何,可以通過指示 AMQ 接受指定包中的序列化對象來實現。 org.springframework.remoting.support 包包含代表遠程方法調用及其結果的主要消息。

com.baeldung.api 包包含我們服務的參數和結果。 添加了 java.lang,因為表示預訂結果的對象引用一個 String,因此我們需要序列化它。

5. 客户端應用程序

5.1. 調用遠程服務

現在讓我們來處理客户端。同樣,我們需要定義調用消息將寫入的隊列。我們需要確認客户端和服務器都使用相同的名稱。

@Bean 
Queue queue() {
    return new ActiveMQQueue("remotingQueue");
}

我們還需要設置一個導出器:

@Bean 
FactoryBean invoker(ConnectionFactory factory, Queue queue) {
    JmsInvokerProxyFactoryBean factoryBean = new JmsInvokerProxyFactoryBean();
    factoryBean.setConnectionFactory(factory);
    factoryBean.setServiceInterface(CabBookingService.class);
    factoryBean.setQueue(queue);
    return factoryBean;
}

我們現在可以像已聲明為本地 Bean 一樣使用遠程服務:

CabBookingService service = context.getBean(CabBookingService.class);
out.println(service.bookRide("13 Seagate Blvd, Key Largo, FL 33037"));

5.2. 運行示例

對於客户端應用程序,我們必須在 <application>.properties 文件中正確選擇值。 在典型的配置中,這些值將與服務器端使用的值完全一致。

這應該足以演示通過 Apache AMQ 進行遠程調用。 因此,我們首先啓動 ApacheMQ,然後是服務器應用程序,最後是調用遠程服務的客户端應用程序。

6. 結論

在本快速教程中,我們看到了如何使用 Spring RemotingAMQ 消息隊列系統之上提供 RPC

Spring Remoting 持續展示了無論底層通道如何,異步調用設置起來都非常簡單。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.