You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring Boot应用中配置不同命名空间的Azure Service Bus队列与主题

在Spring Boot中连接两个不同命名空间的Azure Service Bus(队列+主题,无密码认证)

我有一个Spring Boot应用,原本用于从Azure Service Bus队列读取消息。现在需要新增一个监听器从另一个命名空间的Azure Service Bus主题读取消息,采用无密码认证(不使用连接字符串),但合并配置时遇到问题,无法同时连接两个不同的命名空间。


一、修正依赖配置(pom.xml)

确保依赖结构清晰,版本统一:

<properties>
    <spring-cloud-azure.version>4.17.0</spring-cloud-azure.version>
</properties>

<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-servicebus-jms</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.azure.spring</groupId>
            <artifactId>spring-cloud-azure-dependencies</artifactId>
            <version>${spring-cloud-azure.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

二、修正application.yml配置

不要使用多文档分隔符---(这是环境切换用的,无法同时生效两个命名空间),改为分命名空间配置:

spring:
  jms:
    listener:
      receive-timeout: 60000

# 队列对应的Service Bus命名空间配置
spring.cloud.azure.servicebus.queue-namespace:
  namespace: queue-namespace
  passwordless-enabled: true
  pricing-tier: standard
  credential:
    client-id: 4b41-9a94-67cc176e1f74
  profile:
    tenant-id: ef0-43ca-a603-a8a1e287fa9d

# 主题对应的Service Bus命名空间配置
spring.cloud.azure.servicebus.topic-namespace:
  namespace: topic-namespace
  passwordless-enabled: true
  pricing-tier: standard
  credential:
    client-id: 5e78-4034-a948-44e819798c12
  profile:
    tenant-id: ef0-43ca-a603-a8a1e287fa9d

三、配置自定义JMS连接工厂与监听器容器

编写配置类,创建两个独立的连接工厂和监听器容器,分别对应队列和主题:

import com.azure.spring.cloud.autoconfigure.servicebus.ServiceBusJmsProperties;
import com.azure.spring.cloud.service.servicebus.jms.ServiceBusJmsConnectionFactory;
import com.azure.spring.cloud.service.servicebus.jms.ServiceBusJmsConnectionFactoryBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import javax.jms.ConnectionFactory;

@Configuration
public class MultipleServiceBusConfig {

    // 绑定队列的配置属性
    @Bean
    @ConfigurationProperties("spring.cloud.azure.servicebus.queue-namespace")
    public ServiceBusJmsProperties queueServiceBusProperties() {
        return new ServiceBusJmsProperties();
    }

    // 绑定主题的配置属性
    @Bean
    @ConfigurationProperties("spring.cloud.azure.servicebus.topic-namespace")
    public ServiceBusJmsProperties topicServiceBusProperties() {
        return new ServiceBusJmsProperties();
    }

    // 队列连接工厂
    @Bean(name = "queueJmsConnectionFactory")
    public ServiceBusJmsConnectionFactory queueJmsConnectionFactory() {
        return new ServiceBusJmsConnectionFactoryBuilder()
                .serviceBusJmsProperties(queueServiceBusProperties())
                .build();
    }

    // 主题连接工厂
    @Bean(name = "topicJmsConnectionFactory")
    public ServiceBusJmsConnectionFactory topicJmsConnectionFactory() {
        return new ServiceBusJmsConnectionFactoryBuilder()
                .serviceBusJmsProperties(topicServiceBusProperties())
                .build();
    }

    // 队列监听器容器
    @Bean(name = "queueJmsListenerContainerFactory")
    public JmsListenerContainerFactory<?> queueJmsListenerContainerFactory(ConnectionFactory queueJmsConnectionFactory) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(queueJmsConnectionFactory);
        factory.setReceiveTimeout(60000L);
        return factory;
    }

    // 主题监听器容器(必须设置pubSubDomain为true)
    @Bean(name = "topicJmsListenerContainerFactory")
    public JmsListenerContainerFactory<?> topicJmsListenerContainerFactory(ConnectionFactory topicJmsConnectionFactory) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(topicJmsConnectionFactory);
        factory.setReceiveTimeout(60000L);
        factory.setPubSubDomain(true);
        return factory;
    }
}

四、修正监听器代码

更新监听器的容器工厂引用,确保对应到各自的连接配置:

队列监听器

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class QueueListener {
    private static final Logger log = LoggerFactory.getLogger(QueueListener.class);

    @JmsListener(destination = "queue-name", containerFactory = "queueJmsListenerContainerFactory")
    public void receiveMessage(byte[] message) {
        log.info("Queue Message received: {}", new String(message));
    }
}

主题监听器

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class TopicListener {
    private static final Logger log = LoggerFactory.getLogger(TopicListener.class);

    @JmsListener(destination = "topic-name", subscription = "topic-cription-dev", containerFactory = "topicJmsListenerContainerFactory")
    public void receiveMessage(String message) {
        log.info("Topic Message received: {}", message);
    }
}

关键注意事项

  • 主题监听器的容器工厂必须设置pubSubDomain = true,否则无法正确订阅主题。
  • 无密码认证权限配置:
    • 本地开发:通过az login登录Azure CLI,确保账号拥有对应Service Bus的Azure Service Bus Data Receiver权限。
    • Azure部署:使用托管标识(Managed Identity),并为标识分配对应权限。

内容的提问来源于stack exchange,提问作者Ravi Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 07:44:54