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

Spock测试与Artemis嵌入式服务器:如何在地址上配置消费队列?

解决方案

1. 配置Artemis兼容VirtualTopic路由规则

ActiveMQ Artemis需显式配置地址规则以兼容Classic的VirtualTopic行为,在application.yml中添加嵌入式代理核心配置:

spring:
  artemis:
    embedded:
      config:
        core:
          address-settings:
            # 匹配所有VirtualTopic前缀的地址
            'VirtualTopic.*':
              default-routing-type: MULTICAST
              routing-types: [MULTICAST, ANYCAST]
          addresses:
            VirtualTopic.audit.events:
              routing-types: [MULTICAST]
          queues:
            VirtualTopic.audit.events::junit:
              address: VirtualTopic.audit.events
              routing-type: MULTICAST

此配置让VirtualTopic.audit.events地址以MULTICAST路由运行,队列VirtualTopic.audit.events::junit绑定到该地址的MULTICAST路由,确保主题消息能路由到消费队列。

2. 修正JMS目标解析逻辑

原DynamicDestinationResolver未区分主题发送与队列接收场景,修改如下:

@Bean
public DynamicDestinationResolver dynamicDestinationResolver() {
    return new DynamicDestinationResolver() {
        @Override
        public Destination resolveDestinationName(Session session, String destinationName, boolean pubSubDomain) throws JMSException {
            // VirtualTopic开头且无::后缀的是主题,按发布订阅处理
            if (destinationName.startsWith("VirtualTopic.") && !destinationName.contains("::")) {
                return super.resolveDestinationName(session, destinationName, true);
            }
            // 带::后缀的是消费队列,按点对点处理
            if (destinationName.contains("::")) {
                return super.resolveDestinationName(session, destinationName, false);
            }
            return super.resolveDestinationName(session, destinationName, pubSubDomain);
        }
    };
}

3. 拆分JMS模板配置

全局设置spring.jms.pub-sub-domain=true会导致队列接收也按主题处理,需拆分发送和接收模板:

@Bean
public JmsMessagingTemplate jmsTopicMessagingTemplate(ConnectionFactory connectionFactory) {
    JmsMessagingTemplate template = new JmsMessagingTemplate(connectionFactory);
    template.setPubSubDomain(true); // 专门用于发送主题消息
    return template;
}

@Bean
public JmsMessagingTemplate jmsQueueMessagingTemplate(ConnectionFactory connectionFactory) {
    JmsMessagingTemplate template = new JmsMessagingTemplate(connectionFactory);
    template.setPubSubDomain(false); // 专门用于接收队列消息
    return template;
}

测试中发送用jmsTopicMessagingTemplate,接收用jmsQueueMessagingTemplate。

4. 启用OpenWire协议(兼容旧客户端)

为支持WebLogic等使用OpenWire的旧客户端,在application.yml添加协议配置:

spring:
  artemis:
    embedded:
      config:
        core:
          acceptors:
            openwire-acceptor: tcp://localhost:61616?protocols=OPENWIRE

5. 优化测试代码可靠性

移除不稳定的sleep(1000),改用CountDownLatch实现同步等待:

def 'notify a success status event'() {
    given:
        CountDownLatch latch = new CountDownLatch(1)
        StatusEvent receivedEvent = null
        jmsQueueMessagingTemplate.listen(config.statusEventDestination + "::junit", Message.class) { message ->
            receivedEvent = jsonService.fromString((String) message.payload, StatusEvent.class)
            latch.countDown()
        }
    when:
        Message message = buildMessage(false)
        service.notify(message.headers, message.headers.getId(), StatusType.AUDIT_STORE_SUCCESS)
        latch.await(10, TimeUnit.SECONDS)
    then:
        receivedEvent != null
        receivedEvent.id == message.headers.getId().toString()
        receivedEvent.statusDate != null
        receivedEvent.status == StatusType.AUDIT_STORE_SUCCESS
        receivedEvent.event == StatusEvent.CCNCSI_EVENT_STATUS
        receivedEvent.error == null
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 06:57:05