Spring - JMS,如何在应用程序启动后启动 JMS 并在应用程序关闭时不断尝试重新连接

Spring - JMS , how to start JMS after application is up and continuously try to reconnect if it goes down

我有 spring 应用程序,我试图在其中连接到 JMS activemq 服务器。我的上下文文件内容如下所示:

<bean id="amqPowerConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
    <constructor-arg index="0" value="${power.messagebrokerurl}"/>
</bean>

<bean id="powerConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
    <constructor-arg ref="amqPowerConnectionFactory"/>
</bean>

<bean id="timeSeriesChangesContainer" class="org.springframework.jms.listener.SimpleMessageListenerContainer">
    <property name="connectionFactory" ref="powerConnectionFactory"/>
    <property name="destination" ref="powerEventQueue"/>
    <property name="messageListener" ref="timeSeriesDataAdapter"/>
</bean>

但是如果 JMS 服务器关闭,则服务器不会在启动时初始化 spring 上下文。

我可以将 autoStartup 设置为 false,然后 spring 初始化上下文,但是我该如何手动启动此侦听器?

<bean id="timeSeriesChangesContainer" class="org.springframework.jms.listener.SimpleMessageListenerContainer">
    <property name="connectionFactory" ref="powerConnectionFactory"/>
    <property name="destination" ref="powerEventQueue"/>
    <property name="messageListener" ref="timeSeriesDataAdapter"/>
    <property name="autoStartup" value="false"/>
</bean>

我还需要编写一个连续循环,如果它出现故障,它将尝试重新连接到此 JMS 服务器。

消息侦听器有一个函数 start()。 使用该功能,您可以在程序中手动启动监听器。

至于循环:我们有一个类似的问题,由于系统组件不可用,我们不得不在给定的时间启动和停止侦听器,我们通过计划的作业实现了它。

下面是通过计划作业启动侦听器的示例:

更新:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class StartStopJmsBatch {

private static final Logger LOG = LoggerFactory.getLogger(StartStopJmsBatch.class);

@Autowired
private DefaultMessageListenerContainer messageListenerContainer;

@Scheduled(cron = "0 0 * * * *")
public void startJmsConsumer() {
    if (!messageListenerContainer.isRunning()) {
        LOG.info("Started JmsListenerContainer");
        messageListenerContainer.start();
    }
}
}

我添加了 class 的其余部分。 它使用 spring 的调度机制进行调度(特别是 take a look here 在第 28.4 章) 至于 cron 表达式语法 take a look here

备选

另一种方法是使用 Spring 的 DefaultMessageListenerContainer (take a look here),它具有内置的自我恢复功能,即使 JMS 服务器也应该初始化 spring 上下文在应用程序启动时不可用。

感谢@Wuteb 的回答,我终于如您所说从 SimpleMessageListenerContainer 切换到 DefaultMessageListenerContainer 然后不需要添加任何 class(即 StartStopJmsBatch 如上所述)并且我们必须添加的唯一部分添加是

<bean id="timeSeriesChangesContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="powerConnectionFactory"/>
    <property name="destination" ref="powerEventQueue"/>
    <property name="messageListener" ref="timeSeriesDataAdapter"/>
    <property name="recoveryInterval" value="500"/>
</bean>

其中 recoveryInterval 指定恢复尝试之间的间隔,以毫秒为单位。