使用 Spring 启动和停止 JMS 侦听器

Posted

技术标签:

【中文标题】使用 Spring 启动和停止 JMS 侦听器【英文标题】:Start and Stop JMS Listener using Spring 【发布时间】:2012-07-09 14:33:02 【问题描述】:

所以问题是如何临时停止和启动使用 spring 使用休闲方式创建的 jms 侦听器:

<amq:connectionFactory id="exampleJmsFactory" brokerURL="tcp://$jms.broker.url" />

<jms:listener-container concurrency="1" connection-factory="exampleJmsFactory"  destination-type="queue" message-converter="exampleMessageConverter">
        <jms:listener destination="incoming.example.client.queue" ref="exampleProductsMessageConsumer" method="consume"/>
</jms:listener-container>


<bean id="exampleProductsMessageConsumer" class="com.unic.example.jms.receive.JmsExampleProductsMessageConsumer" scope="tenant"/>

所以基本上是什么问题。我们确实有一个客户端可以随时运行的初始化/更新机制,并且在此初始化/更新期间,我想停止使用任何消息,因为此时系统无法使用,如果有消息出现,它将丢失。

那么我如何使用 API 停止侦听器或侦听器容器或整个连接。我发现一个类 AbstractJmsListeningContainer 有停止/启动但我怎么能得到它?我的意思是这些 jms: listener 和 listener-containers 都没有名称或类似名称。

【问题讨论】:

【参考方案1】:

您还可以获取 messageListenerContainer,并在其上调用 stop():

@javax.annotation.Resource //autowire by name
 private AbstractJmsListeningContainer myMessageListenerContainer;

 myMessageListenerContainer.stop();

 I'm using the more verbose setup of this container:
 <bean id="myMessageListenerContainer" class="org.springframework.jms.listener.DefaultMes sageListenerContainer">
 <property name="connectionFactory" ref="jmsConnectionFactory"/>
 <property name="destination" ref="myQueue"/>
 <property name="messageListener" ref="myListener"/>
 <property name="autoStartup" value="true" />
 </bean>

在这里您看到如果您不希望 listenerContainer 自动启动,可以将 autoStartup 设置为 false。

【讨论】:

【参考方案2】:

是的,这就是诀窍。

<jms:listener-container concurrency="1" connection-factory="exampleJmsFactory"  destination-type="queue" message-converter="exampleMessageConverter">
        <jms:listener id="exampleProductsMessageListener" destination="incoming.example.client.queue" ref="exampleProductsMessageConsumer" method="consume"/>
</jms:listener-container>



DefaultMessageListenerContainer exampleProductsMessageListener= Registry.getApplicationContext().getBean("exampleProductsMessageListener", DefaultMessageListenerContainer.class);
exampleProductsMessageListener.stop();

【讨论】:

当我有 10 个侦听器,调用相同的消费方法时,这有多糟糕。首先,我必须确定哪个侦听器正在调用我的消耗方法。这会使这段代码变得繁琐。您对同一目标还有其他建议吗? @JOKe 当我stop() 我的听众时,isRunning() 返回 False,但我仍然通过 MQueue 收到消息...知道吗?【参考方案3】:

您可以为侦听器容器分配一个 id。然后通过调用 getBean 或将其注入来获取对它的引用。这将为您提供一个 AbstractJmsListeningContainer ,您可以在其上调用 start / stop。

【讨论】:

首先我不能将 id 真正分配给侦听器容器。第二个问题是,实际上我有 3 个侦听器而不仅仅是一个,所以它是 1 个带有 3 个侦听器的侦听器容器,所以如果我尝试通过 DefaultMessageListenerContainer 或 AbstractJmsListeningContainer 类获取它告诉我它找到了 3。我猜它创建的每个侦听器一个监听器容器,所以我不能真正按类/类型查找 啊监听器对象本身有一个 id 传递给容器让我试试

以上是关于使用 Spring 启动和停止 JMS 侦听器的主要内容,如果未能解决你的问题,请参考以下文章

如何在启动时以编程方式禁用 Spring @JmsListener

如何使用 Spring JMS 在 ActiveMQ 中创建多个侦听器

Spring Boot JMS 侦听器:无法刷新目标的 JMS 连接

为 JMS 侦听器处理 Spring Security 的首选方法是啥?

使用线程池的 JMS 侦听器

如何配置和启用 JMS 侦听器以根据某些条件使用消息?