濤。

t.

SpringBoot集成mqtt启动就不断报已断开连接问题

踩坑记录,实在是天坑!!!

原因一:clientId相同,即clientId重复导致(不过我不是这个问题)

我的问题是:

项目启动成功后,控制台不停地反复输出:已断开连接,,,

加了重连机制后,则不停地输出:重连失败,已连接客户机,,,

尼玛,,关键点还在于我能接收到订阅的消息(不影响消息处理),这又是什么情况,明明没断连,确一直报已断开连接

百度了半天,愣是找不到对的方法

原因二:项目启动类用了ApplicationListener(就是这个原因,改为ApplicationRunner就行了)

附成功代码:::

maven依赖

<!-- mqtt -->
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-mqtt</artifactId>
</dependency>

yaml文件

#mqtt配置
mqtt:
  # 服务器连接地址,如果有多个,用逗号隔开
  url: tcp://127.0.0.1:1883
  # 连接服务器默认客户端ID
  clientId: ${random.value}
  # 主题
  topics: topic-docker
  # 用户名
  username: admin
  # 密码
  password: admin
  # 连接超时
  timeout: 30
  # 保持活动间隔
  keepalive: 60

mqtt配置类

package com.wt.mqtt;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * mqtt信息
 *
 * @author wt
 **/
@Data
@Component
public class MqttConfig {

    @Value("${mqtt.url}")
    private String url;
    @Value("${mqtt.clientId}")
    private String clientId;
    @Value("${mqtt.username}")
    private String username;
    @Value("${mqtt.password}")
    private String password;
    @Value("${mqtt.topics}")
    private String subtopic;
    @Value("${mqtt.timeout}")
    private Integer timeout;
    @Value("${mqtt.keepalive}")
    private Integer keepalive;

}

mqtt启动类


package com.hzzcdz.job.mqtt;

import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
* 项目启动 订阅主题
*
* @author wangtao
*/
@Slf4j
@Component
public class MqttManager implements ApplicationRunner {

@Resource
private MqttConfig mqttConfig;

@Resource
private MyCallback callback;

private final MqttConnect server;

@Autowired
public MqttManager(MqttConnect server) {
this.server = server;
}

@Override
public void run(ApplicationArguments args) {
try {
server.setMqttClient(mqttConfig.getUsername(), mqttConfig.getPassword(), callback);
server.sub(mqttConfig.getSubtopic());
log.info("MQTT启动连接成功!");
log.info("订阅的主题是 : " + mqttConfig.getSubtopic());
} catch (MqttException e) {
log.error(e.getMessage(), e);
log.error("MQTT启动连接失败!");
}
}
}

mqtt连接工具类

package com.hzzcdz.job.mqtt;


import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @author wt
 * MQTT工具类操作
 */
@Slf4j
@Component
public class MqttConnect {

    @Resource
    private MqttConfig mqttConfig;

    private MqttClient mqttClient;

    /**
     * 客户端connect连接mqtt服务器
     *
     * @param userName     用户名
     * @param passWord     密码
     * @param mqttCallback 回调函数
     **/
    public void setMqttClient(String userName, String passWord, MqttCallback mqttCallback) throws MqttException {
        MqttConnectOptions options = mqttConnectOptions(userName, passWord);
        mqttClient.setCallback(mqttCallback);
        mqttClient.connect(options);
    }

    /**
     * MQTT连接参数设置
     */
    private MqttConnectOptions mqttConnectOptions(String userName, String passWord) throws MqttException {
        mqttClient = new MqttClient(mqttConfig.getUrl(), mqttConfig.getClientId(), new MemoryPersistence());
        MqttConnectOptions options = new MqttConnectOptions();
        //用户名
        options.setUserName(userName);
        //密码
        options.setPassword(passWord.toCharArray());
        //连接超时,默认:30
        options.setConnectionTimeout(mqttConfig.getTimeout());
        //自动重新连接,默认:false
        options.setAutomaticReconnect(false);
        //清理会话,默认:true
        options.setCleanSession(false);
        //保持活动间隔,默认:60
        options.setKeepAliveInterval(mqttConfig.getKeepalive());
        return options;
    }

    /**
     * 关闭MQTT连接
     */
    public void close() throws MqttException {
        mqttClient.close();
        mqttClient.disconnect();
    }

    /**
     * 重连
     */
    public void reConnect(String topic) {
        try {
            mqttClient.reconnect();
            while (true) {
                if (mqttClient.isConnected()) {
                    sub(topic);
                    break;
                } else {
                    Thread.sleep(10000);
                    log.info("重连中,请稍后......");
                }
            }
            log.info("MQTT连接成功,订阅成功.topic={}", topic);
        } catch (MqttException | InterruptedException e) {
            log.error("重连失败,失败原因{}", e.getMessage());
        }
    }

    /**
     * 向某个主题发布消息 默认qos:1
     *
     * @param topic:发布的主题
     * @param msg:发布的消息
     */
    public void pub(String topic, String msg) throws MqttException {
        MqttMessage mqttMessage = new MqttMessage();
        mqttMessage.setPayload(msg.getBytes());
        MqttTopic mqttTopic = mqttClient.getTopic(topic);
        MqttDeliveryToken token = mqttTopic.publish(mqttMessage);
        token.waitForCompletion();
    }

    /**
     * 向某个主题发布消息
     *
     * @param topic: 发布的主题
     * @param msg:   发布的消息
     * @param qos:   消息质量    Qos:0、1、2
     */
    public void pub(String topic, String msg, int qos) throws MqttException {
        MqttMessage mqttMessage = new MqttMessage();
        mqttMessage.setQos(qos);
        mqttMessage.setPayload(msg.getBytes());
        MqttTopic mqttTopic = mqttClient.getTopic(topic);
        MqttDeliveryToken token = mqttTopic.publish(mqttMessage);
        token.waitForCompletion();
    }

    /**
     * 订阅某一个主题 ,此方法默认的的Qos等级为:1
     *
     * @param topic 主题
     */
    public void sub(String topic) throws MqttException {
        mqttClient.subscribe(topic);
    }

    /**
     * 订阅某一个主题,可携带Qos
     *
     * @param topic 所要订阅的主题
     * @param qos   消息质量:0、1、2
     */
    public void sub(String topic, int qos) throws MqttException {
        log.info("订阅的主题是 : " + topic);
        log.info("订阅的Qos是 : " + qos);
        mqttClient.subscribe(topic, qos);
    }

    /**
     * 取消某个主题发布消息
     */
    public void unSub(String topic) {
        log.info("取消订阅的主题是 : " + topic);
        try {
            mqttClient.unsubscribe(topic);
        } catch (MqttException e) {
            throw new RuntimeException(e);
        }
    }


}

mqtt回调函数类

package com.hzzcdz.job.mqtt;

import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * MQTT回调函数
 *
 * @author wt
 */
@Slf4j
@Component
public class MyCallback implements MqttCallback {

    @Resource
    private MqttConfig mqttConfig;

    @Resource
    private MqttConnect mqttConnect;


    /**
     * MQTT 断开连接会执行此方法
     */
    @Override
    public void connectionLost(Throwable throwable) {
        log.info("断开了MQTT连接 :{}", throwable.getMessage());
        log.error(throwable.getMessage(), throwable);
        mqttConnect.reConnect(mqttConfig.getSubtopic());

    }

    /**
     * publish发布成功后会执行到这里
     */
    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        log.info("发布消息成功");
    }

    /**
     * subscribe订阅后得到的消息会执行到这里
     */
    @Override
    public void messageArrived(String topic, MqttMessage message) {
        //  TODO    此处可以将订阅得到的消息进行业务处理、数据存储
        log.info("收到来自 " + topic + " 的消息:{}", new String(message.getPayload()));
    //数据处理

} }

 

至此填上了坑!!!

 

 

posted on 2024-04-07 16:58  濤。  阅读(711)  评论(0编辑  收藏  举报

导航