如何在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
相关产品推荐
相关产品推荐

