解决mqtt messageArrived()方法调用操作数据库方法断开连接问题

在springboot中整合mqtt 在回调方法 messageArrived()获取数据 如果直接操作数据库会使用连接断开

解决方法:把要操作数据库的方法封装到回调类,在本类中调用

先把mapper注入进来

具体原因可以看我上一篇博客 https://blog.csdn.net/qq_41249513/article/details/108464133

 

 

整个类写法

package com.laima.operate.voltoperate.mqtt;

/**
 * @Author: wrc
 * @Classname PushCallback
 * @Description TODO
 * @Date 2020/9/7 16:52
 * @Created wrc
 */

import com.laima.operate.voltoperate.dao.ElecMeasuringPointDao;
import com.laima.operate.voltoperate.entity.ElecMeasuringPointEntity;
import com.laima.operate.voltoperate.service.ElecMeasuringPointService;
import com.sun.javafx.image.impl.IntArgb;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * 发布消息的回调类
 *
 * 必须实现MqttCallback的接口并实现对应的相关接口方法CallBack 类将实现 MqttCallBack。
 * 每个客户机标识都需要一个回调实例。在此示例中,构造函数传递客户机标识以另存为实例数据。
 * 在回调中,将它用来标识已经启动了该回调的哪个实例。
 * 必须在回调类中实现三个方法:
 *
 *  public void messageArrived(MqttTopic topic, MqttMessage message)接收已经预订的发布。
 *
 *  public void connectionLost(Throwable cause)在断开连接时调用。
 *
 *  public void deliveryComplete(MqttDeliveryToken token))
 *  接收到已经发布的 QoS 1 或 QoS 2 消息的传递令牌时调用。
 *  由 MqttClient.connect 激活此回调。
 *
 */
@Component
public class PushCallback implements MqttCallback {

    private static final Logger LOGGER = LoggerFactory.getLogger(PushCallback.class);


    @Autowired
    public ElecMeasuringPointDao elecMeasuringPointDao;

    public  static PushCallback PushCallback ;

    @PostConstruct //通过@PostConstruct实现初始化bean之前进行的操作
    public void init() {
        System.out.println("初始化");
        PushCallback = this;
        PushCallback.elecMeasuringPointDao = this.elecMeasuringPointDao;
    }

    /**
     * 主题
     */
    private String topic = "voltceshi";//测试

//    private String topic = "正式环境主题";//正式

    private MQTTSubsribe mqttSubsribe;
//    private MQTTSubsribe mqttSubsribe = new MQTTSubsribe();



    public PushCallback(MQTTSubsribe subsribe) {
        this.mqttSubsribe = subsribe;
    }

    //这是封装mapper的插入方法,解决插入数据连接断开
    public int insert(ElecMeasuringPointEntity elecMeasuringPointEntity ){
        return elecMeasuringPointDao.insert(elecMeasuringPointEntity);
    }


    @Override
    public void connectionLost(Throwable cause) {
        // 连接丢失后,一般在这里面进行重连
        LOGGER.info("---------------------连接断开,可以做重连");
        // deliveryComplete(null);

        while (true){
            try {//如果没有发生异常说明连接成功,如果发生异常,则死循环
                Thread.sleep(1000);
                mqttSubsribe.init();
                break;
            }catch (Exception e){
//                e.printStackTrace();
                continue;
            }
        }

    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        System.out.println("deliveryComplete---------" + token.isComplete());
    }

    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {
        // subscribe后得到的消息会执行到这里面
        String result = new String(message.getPayload(),"UTF-8");
        System.out.println("接收消息主题 : " + topic);
        System.out.println("接收消息Qos : " + message.getQos());
        System.out.println("接收消息内容 : " + result);

        //这里可以针对收到的消息做处理
        ElecMeasuringPointEntity elecMeasuringPointEntity = new ElecMeasuringPointEntity();
        elecMeasuringPointEntity.setUEnterpriseId(1111);
        //插入方法
        PushCallback.elecMeasuringPointDao.insert(elecMeasuringPointEntity);

        //elecMeasuringPointService.insert(elecMeasuringPointEntity);
    }



}

 

 

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 18
    评论
MQTT消息到达回调方法中执行数据库操作,有可能会导致连接断开的情况。这是因为在回调方法中执行数据库操作时,可能会造成阻塞,导致MQTT客户端无法及时响应MQTT代理服务器的心跳包,从而被服务器判定为连接断开。 为了避免这种情况,我们可以采用异步方式处理数据库操作,或者将数据库操作放到另外一个线程中执行。在Python中,可以使用异步库如asyncio或者线程库如threading来实现。 下面是一个使用asyncio库处理数据库操作的示例代码: ```python import asyncio import paho.mqtt.client as mqtt async def process_message(message): # 处理MQTT消息 pass async def on_message(client, userdata, message): asyncio.create_task(process_message(message)) client = mqtt.Client() client.on_message = on_message # 连接MQTT代理服务器 client.connect("localhost", 1883) # 订阅MQTT主题 client.subscribe("test/topic") # 开始MQTT循环 client.loop_start() # 进入异步事件循环 asyncio.get_event_loop().run_forever() ``` 在上面的代码中,我们使用asyncio库定义了一个名为process_message的异步函数,用于处理MQTT消息。在on_message回调函数中,我们调用了asyncio.create_task方法,将消息处理任务交给异步事件循环去处理。 这样做的好处是,当有大量消息需要处理时,异步事件循环可以自动调度协程,避免协程阻塞导致MQTT连接断开。同时,由于协程是轻量级的,因此可以同时处理多个请求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值