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

如何用STOMP客户端连接Spring Boot JMS创建的ActiveMQ Artemis队列

问题

我正在学习SpringJMS和消息中间件(MOM),用ActiveMQ Artemis做实践。通过jakarta.jms.* API创建队列目标地址,比如传入IDuser12345abc时,会生成路由类型为ANYCAST的队列地址user12345abc并发送测试消息。现在想用STOMP写前端连接这个队列,但订阅jms.queue.user12345abc时会创建新的队列地址,而非连接已有的队列。已经配置了Spring后端的StompBrokerRelay,但问题依然存在。想问下是不是有概念误解?怎么用STOMP连接之前用JMS创建的队列?

创建队列的代码

public void createUserDestination(String userId) throws JMSException {
        queueDestination = setupConnection().createQueue("user" + userId);
        producer = session.createProducer(queueDestination);
        producer.setDeliveryMode(DeliveryMode.PERSISTENT);
        producer.send(session.createTextMessage("Testing queue availability"));

        connection.close();
        log.info("successfully created group... going back to controller");
}

STOMP订阅代码

stompClient.subscribe("jms.queue.user12345abc", (message) => {
               receivedMessages.value.push(message.body);
 });

Spring配置代码

public void configureMessageBroker(MessageBrokerRegistry registry) {
        // these two end points are prefixes for where the messages are pushed to
        registry.enableStompBrokerRelay("jms.topic", "jms.queue")
            .setRelayHost("127.0.0.1")
            .setRelayPort(61613)
            .setSystemLogin(brokerUsername)
            .setSystemPasscode(brokerPassword)
            .setClientLogin(brokerUsername)
            .setClientPasscode(brokerPassword);

        // this prefixes the end points where clients send messages
        registry.setApplicationDestinationPrefixes("/app", "jms.topic", "jms.queue");

        // this prefixes the end points where the user's subscribe to
        registry.setUserDestinationPrefix("/user");
}

解答

核心概念澄清

ActiveMQ Artemis采用地址-队列分离的模型,和传统JMS的队列/主题模型有本质差异:

  • 你用JMS createQueue("user12345abc")时,Artemis会自动创建:
    1. 名为user12345abc的地址,路由类型为ANYCAST
    2. 绑定到该地址的队列,名称同样是user12345abc
  • Spring StompBrokerRelay的jms.queue.XXX前缀,会将STOMP目标映射为JMS队列XXX。但如果映射后的队列在Artemis中不存在,默认配置下Artemis会自动创建新的地址和队列,这就是你看到“新建队列”的原因——要么之前创建的队列已被自动删除,要么映射逻辑没匹配到已有资源。

具体解决步骤

  1. 确认已有队列状态
    登录Artemis控制台(默认地址http://localhost:8161),进入「Addresses」页面,检查是否存在user12345abc地址,以及对应的user12345abc队列。如果不存在,说明之前JMS创建的队列被自动删除了——可以在Artemis的broker.xml中确认auto-delete-queues=false(默认值为false,若修改过配置需核对),确保持久化队列不会随连接关闭而删除。

  2. 调整STOMP目标与Spring配置
    你当前的配置逻辑没问题,但可以换更直观的映射方式避免混淆:

    • 修改Spring配置,将Broker转发前缀改为/queue和/topic:
      registry.enableStompBrokerRelay("/queue", "/topic")
          .setRelayHost("127.0.0.1")
          .setRelayPort(61613)
          .setSystemLogin(brokerUsername)
          .setSystemPasscode(brokerPassword)
          .setClientLogin(brokerUsername)
          .setClientPasscode(brokerPassword);
      
    • 前端STOMP订阅目标改为/queue/user12345abc:
      stompClient.subscribe("/queue/user12345abc", (message) => {
          receivedMessages.value.push(message.body);
      });
      
      StompBrokerRelay会自动将/queue/XXX映射为JMS队列XXX,直接匹配你之前用JMS创建的队列资源。
  3. 移除配置冲突项
    你的Spring配置中,setApplicationDestinationPrefixes包含了jms.topic和jms.queue,这会导致客户端发送到这些前缀的消息被路由到Spring控制器,而非直接转发到Broker。虽然订阅操作不受影响,但建议移除这两个前缀避免潜在混淆:

    registry.setApplicationDestinationPrefixes("/app");
    
  4. 验证账号权限
    确保StompBrokerRelay使用的登录账号拥有访问user12345abc队列的权限,否则可能触发Artemis创建新的受限队列。

内容的提问来源于stack exchange,提问作者Bikathi Martin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 19:05:23