springboot 用spring-integration-mqtt连接MQTT服务断链重连不重新订阅topic解决办法

907 阅读1分钟

问题描述

在springboot 中用spring-integration-mqtt 连接 MQTT Broker,如果 MQTT Broker长时间重启或主动踢掉客户端连接,当 MQTT Broker重新启动后,客户端主动重连后,不会重新订阅之前的topic

解决办法

1、定义一个重连成功的事件

import org.springframework.integration.mqtt.event.MqttIntegrationEvent;

/**
 * @author Gary Russell
 * @since 4.2.2
 *
 */
@SuppressWarnings("serial")
public class MqttReconnectSuccessEvent extends MqttIntegrationEvent {

   private final String message;

   public MqttReconnectSuccessEvent(Object source, String message) {
      super(source);
      this.message = message;
   }

   public String getMessage() {
      return this.message;
   }

   @Override
   public String toString() {
      return "MqttReconnectSuccessEvent [message=" + this.message + ", source=" + source + "]";
   }

}

2、修改 MqttPahoMessageDrivenChannelAdapter 类源码 一种方法就是下载spring-integration-mqtt的源码改完后重新打包,并引用新的包,另一种就是把MqttPahoMessageDrivenChannelAdapter类的源码拷贝到我们的项目里,直接在里面改。 修改MqttPahoMessageDrivenChannelAdapter里的public void connectComplete(boolean reconnect, String serverURI)方法。

/**
 * 重新此方法,在重连成功后通知出去了
 *
 * @param reconnect If true, the connection was the result of automatic reconnect.
 * @param serverURI The server URI that the connection was made to.
 */
@Override
public void connectComplete(boolean reconnect, String serverURI) {
   if (!reconnect) {
      subscribe();
   } else {
      logger.debug("重连成功");
      ApplicationEventPublisher applicationEventPublisher = getApplicationEventPublisher();
      if (applicationEventPublisher != null) {
         applicationEventPublisher.publishEvent(new MqttReconnectSuccessEvent(this, "重连成功"));
      }
   }
}

3、监听MqttReconnectSuccessEvent事件

/**
 * 处理重连不订阅topic的问题
 * @param event
 */
@EventListener
public void handleMqttReconnectSuccessEvent(MqttReconnectSuccessEvent event) {
    MqttPahoMessageDrivenChannelAdapter adapter = (MqttPahoMessageDrivenChannelAdapter) event.getSource();
    String[] topics = adapter.getTopic();
    if (topics != null) {
        adapter.removeTopic(topics);
        adapter.addTopic(topics);
    }
    log.info("重新订阅topic成功");
}

此处需要先把之前订阅的topic取消订阅,因为之前的topic数据一直保存在内存中的。

通过上面这样就可以解决在springboot中用spring-integration-mqtt连接MQTT服务重连成功后不重新订阅topic的问题。