Spring Boot + ActiveMQ以编程方式即时订阅主题

时间:2018-05-14 12:28:34

标签: java spring spring-boot activemq spring-jms

我正在尝试实现一个功能,其中我拥有的侦听器类可以订阅/取消订阅JMS主题。 经过一些研究后,我们没有看到明确的方法来做到这一点,我已经提出了两个解决方案:

  1. 有一个侦听器类,其中包含一个String主题名称列表,并定期运行它应该订阅的所有这些主题,并在每个主题上运行阻塞jmsTemplate.receiveAndConvert(topicName)(可能将阻塞操作本身委派给一个工作池)。 从主题订阅/取消订阅就像从列表中删除主题名称一样简单。
  2. 有一个工厂类,它将为应用程序需要订阅的每个主题构建一个新的侦听器,使用如下方法:

    public MessageListenerContainer createListener(String topic) {
      DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
      container.setConnectionFactory(connectionFactory());
      container.setDestinationName(topic);
      container.setMessageListener(new MyListenerClass());
      return container;
    

    }

  3. 第二种选择对我来说似乎更优雅,但我不确定听众的生命周期。我浏览了一下spring boot的jms和activemq模块的源代码,并注意到DefaultMessageListenerContainer有方法initialize()start(),但我不确定如何/如果我需要使用这些,因为我可以找到以这种方式构建MessageListenerContainer的唯一方法是Bean声明。 此外,当取消订阅主题时,因此想要销毁与之关联的侦听器容器,除了调用stop(callback)方法之外还需要做更多的工作吗?

    我对JMS / ActiveMQ及其Spring集成的理解是否正确,因为没有更简单的方法来实现这一点?我的方法是否正确?

2 个答案:

答案 0 :(得分:2)

恕我直言,只要你

  • 从spring获取connectionFactory( a PooledConnectionFactory
  • 在订阅时正确拨打initialise()start(),并stop()取消订阅
  • 如果发生异常,请不要指望重新发送消息

第二种方法一切都应该没问题

答案 1 :(得分:0)

要在运行时注册新的JmsListenerEndpoint,您必须完成2个步骤

1创建自定义MessageListener服务

@Service
public class CustomMessageListener implements MessageListener {
    public void onMessage(Message message) {
        TextMessage textMessage = (TextMessage) message;
        try {
            System.out.println("[Custom message listener] " + textMessage.getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

2使用JmsListenerEndpointRegistry

注册新端点
@Service
public class MessageListenersService {
    @Autowired
    private JmsListenerEndpointRegistry registry;

    @Autowired
    @Qualifier("containerFactory")
    private DefaultJmsListenerContainerFactory factory;

    public void registerListener(String queueNameToListen, MessageListener listener) {
        SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
        endpoint.setId("ep-"+listener.hashCode()); // ID is mandatory
        endpoint.setMessageListener(listener);
        endpoint.setDestination(queueNameToListen);
        registry.registerListenerContainer(endpoint, factory, true);
    }
}

使用它

    private static final String CUSTOM_DESTINATION = "queue-42";

    @Autowired
    MessageListenersService messageListenersService;
    @Autowired
    CustomMessageListener customMessageListener;
    @Autowired
    JmsTemplate jmsTemplate;

    @PostConstruct
    public void createCustomListener() throws InterruptedException {
        messageListenersService.registerListener(CUSTOM_DESTINATION, customMessageListener);
        jmsTemplate.send(CUSTOM_DESTINATION, session -> session.createTextMessage("hello world"));

        // wait your message:
        TimeUnit.SECONDS.sleep(1);
    }