停止SpringJMS消息侦听器

停止SpringJMS消息侦听器,spring,spring-jms,jmstemplate,Spring,Spring Jms,Jmstemplate,我有一个场景,需要停止spring的DefaultMessageListenerContainer,然后再重新启动它。我有10个不同的DefaultMessageListenerContainer侦听10个不同的队列。 所有10个不同的容器都在调用相同消息侦听器类的相同方法。 现在,我想根据在onMessage方法中得到的异常情况,停止特定队列的messagelistenercontainer。 请建议我如何实现上述情景 下面是我的侦听器配置 <bean id="msglistenerFo

我有一个场景,需要停止spring的DefaultMessageListenerContainer,然后再重新启动它。我有10个不同的DefaultMessageListenerContainer侦听10个不同的队列。 所有10个不同的容器都在调用相同消息侦听器类的相同方法。 现在,我想根据在onMessage方法中得到的异常情况,停止特定队列的messagelistenercontainer。 请建议我如何实现上述情景

下面是我的侦听器配置

<bean id="msglistenerForAuditError" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="jmsFactory"/>
        <property name="sessionTransacted" value="true"/>
        <property name="destinationName" value="test.audit.error2"/>
        <property name="messageListener" ref="auditerrorListener" />
    </bean>

    <bean id="msglistenerForAuditEvent" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="jmsFactory"/>
        <property name="sessionTransacted" value="true"/>
        <property name="destinationName" value="test.audit.event2"/>
        <property name="messageListener" ref="auditerrorListener" />
    </bean>

DefaultMessageListenerContainer是一个生命周期bean,因此它公开了一个
start
stop
方法,您可以分别使用该方法启动和停止侦听器

您可以自己构建一个服务来收集上下文中所有已知的实例,然后可以循环这些实例来停止容器,比如

@Service
public class MyService {

    private final Collection<DefaultMessageListenerContainer> containers;

    @Autowired
    public MyService(Collection<DefaultMessageListenerContainer> containers) {
        this.containers = containers;
    }

    public void stopAll() {
        // iterate over the collection and call "stop()" on each item
    }
}
@服务
公共类MyService{
私人最终收集容器;
@自动连线
公共MyService(收集容器){
这个。容器=容器;
}
公开作废stopAll(){
//迭代集合并对每个项调用“stop()”
}
}
也就是说:

  • 您不应该将此服务作为消息侦听器的一部分调用,因为在线程处理消息时尝试停止容器会产生奇怪的副作用
  • 整个用例在我看来是可疑的。你的信息听众应该是有弹性的,更重要的是,他们应该相互独立;如果您因为侦听器B抛出异常而停止侦听器A,那么您的设计肯定有问题

  • DefaultMessageListenerContainer
    是一个生命周期bean,因此它公开了一个
    start
    和一个
    stop
    方法,您可以分别使用该方法启动和停止侦听器

    您可以自己构建一个服务来收集上下文中所有已知的实例,然后可以循环这些实例来停止容器,比如

    @Service
    public class MyService {
    
        private final Collection<DefaultMessageListenerContainer> containers;
    
        @Autowired
        public MyService(Collection<DefaultMessageListenerContainer> containers) {
            this.containers = containers;
        }
    
        public void stopAll() {
            // iterate over the collection and call "stop()" on each item
        }
    }
    
    @服务
    公共类MyService{
    私人最终收集容器;
    @自动连线
    公共MyService(收集容器){
    这个。容器=容器;
    }
    公开作废stopAll(){
    //迭代集合并对每个项调用“stop()”
    }
    }
    
    也就是说:

  • 您不应该将此服务作为消息侦听器的一部分调用,因为在线程处理消息时尝试停止容器会产生奇怪的副作用
  • 整个用例在我看来是可疑的。你的信息听众应该是有弹性的,更重要的是,他们应该相互独立;如果您因为侦听器B抛出异常而停止侦听器A,那么您的设计肯定有问题

  • DefaultMessageListenerContainer上的stop方法不起作用,但shutdown方法工作正常

     for(DefaultMessageListenerContainer defaultCont:containers){
             defaultCont.shutdown();
          }
    

    DefaultMessageListenerContainer上的stop方法不起作用,但shutdown方法工作正常

     for(DefaultMessageListenerContainer defaultCont:containers){
             defaultCont.shutdown();
          }
    

    注入DefaultMessageListenerContainer集合对我不起作用,我使用SpringBoot1.4.x和Spring4.3.x

    我是这样解决的:

    package org.example.queue;
    
    import org.springframework.jms.config.JmsListenerEndpointRegistry;
    //import other stuffs
    
    @Component
    public class QueueManager {
    
    
       @Autowired
       JmsListenerEndpointRegistry endpointRegistry;
    
    
        public void shutdown() {
            endpointRegistry.getListenerContainers().forEach((container) -> {
                if (container.isRunning()) {
                    log.debug("Shutting down listener: " + container.getClass().getName());
                    container.stop();
                }
            });
        }
    
        public void start() {
            endpointRegistry.getListenerContainers().forEach((container) -> {
                if (!container.isRunning()) {
                    log.debug("Starting listener: " + container.getClass().getName());
                    container.start();
                }
            });
        }
    
    }
    

    注入DefaultMessageListenerContainer集合对我不起作用,我使用SpringBoot1.4.x和Spring4.3.x

    我是这样解决的:

    package org.example.queue;
    
    import org.springframework.jms.config.JmsListenerEndpointRegistry;
    //import other stuffs
    
    @Component
    public class QueueManager {
    
    
       @Autowired
       JmsListenerEndpointRegistry endpointRegistry;
    
    
        public void shutdown() {
            endpointRegistry.getListenerContainers().forEach((container) -> {
                if (container.isRunning()) {
                    log.debug("Shutting down listener: " + container.getClass().getName());
                    container.stop();
                }
            });
        }
    
        public void start() {
            endpointRegistry.getListenerContainers().forEach((container) -> {
                if (!container.isRunning()) {
                    log.debug("Starting listener: " + container.getClass().getName());
                    container.start();
                }
            });
        }
    
    }
    

    我需要实现JMS重新交付,下面是我的用例的步骤。1.>我将有一个quartz调度程序,它将启动两个侦听器,比如a和B。2.>两个侦听器都将使用所有消息,或者如果onMessage期间出现任何异常,则特定侦听器将停止处理,直到下一个调度启动。请建议我如何实现上述过程,或者有任何其他jms重新交付方法还有一件事我不需要停止侦听器A,因为侦听器B引发了异常。如果侦听器B的消息出现异常,我需要停止侦听器B。同样,这是正确的方法吗?这对我@resource private final DefaultMessageListenerContainer有效;这将给我们容器对象的保持,我们可以分别停止和启动容器。但这也仅限于单个容器。我需要实现JMS重新交付,下面是我的用例步骤。1.>我将有一个quartz调度程序,它将启动两个侦听器,比如a和B。2.>两个侦听器都将使用所有消息,或者如果onMessage期间出现任何异常,则特定侦听器将停止处理,直到下一个调度启动。请建议我如何实现上述过程,或者有任何其他jms重新交付方法还有一件事我不需要停止侦听器A,因为侦听器B引发了异常。如果侦听器B的消息出现异常,我需要停止侦听器B。同样,这是正确的方法吗?这对我@resource private final DefaultMessageListenerContainer有效;这将给我们容器对象的保持,我们可以分别停止和启动容器。但这也仅限于单个容器。知道它如何重新启动吗?要重新启动它,请调用start()知道它如何重新启动吗?要重新启动它,请调用start()