mqtt的使用 broker:EMQ

MqttConfig类

package cm.soft.collect.config;

import cm.soft.collect.biz.CollectBiz;
import cm.soft.collect.service.OnMqttCallBack;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Configuration
@PropertySource("classpath:/application.yml")
public class MqttConfig implements AutoCloseable {

    @Autowired
    LogConfig log;
    @Autowired
    CollectBiz collectBiz;
    @Value("${mqtt.username}")
    private String username;
    @Value("${mqtt.password}")
    private String password;
    @Value("${mqtt.subTopics}")
    private String SUB_TOPICS;
    @Value("${mqtt.topic}")
    private String defaultTopic;
    @Value(("${mqtt.brokerUrl}"))
    private String brokerUrl;
    @Value("${mqtt.clientId}")
    private String clientId;

    private int qos = 0;// 默认等级
    private final MemoryPersistence persistence;
    private final ExecutorService executorService;// 启动关闭连接
    private final MqttConnectOptions options;// 连接选项
    private final DisconnectedBufferOptions disconnectedBufferOptions;// 初始化连接必须,  连接成功之后设置连接断开的缓冲配置
    private volatile IMqttAsyncClient mqttClient;

    public MqttConfig() {
        this.disconnectedBufferOptions = new DisconnectedBufferOptions();
        this.options = new MqttConnectOptions();
        this.persistence = new MemoryPersistence();
        this.executorService = Executors.newSingleThreadExecutor();
    }

    @PostConstruct
    private void init() {
        // 初始化options
        options.setServerURIs(new String[]{brokerUrl});
        options.setUserName(username);
        options.setPassword(password.toCharArray());
        options.setConnectionTimeout(0);// 防止 ERROR o.e.p.c.mqttv3.internal.ClientState - Timed out as no activity  错误
        options.setKeepAliveInterval(200);// 设置会话心跳时间,单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
        options.setCleanSession(false); // 设置是否清空session,这里设置为true表示每次连接到服务器都以新身份连接
        options.setAutomaticReconnect(true);// 自动重连
        //表示允许多大数量的QoS为1或2消息被同时进行传输处理。这些消息包括正在进行握手的消息和进行重新发送的消息。默认为20个,
        //如果设置为0,表示不设限制;如果为1,则会确保消息被顺序处理。
        // options.setMaxInflight();
        // 初始化disconnectedBufferOptions
        disconnectedBufferOptions.setBufferSize(100);//离线后最多缓存100条
        disconnectedBufferOptions.setPersistBuffer(false);  //不一直持续留存
        disconnectedBufferOptions.setDeleteOldestMessages(false);//删除旧消息
        disconnectedBufferOptions.setBufferEnabled(true);// 断开连接后进行缓存

        // 初始化mqttClient
        if (mqttClient == null) {
            mqttClient = getMqqtClient();
        }

        ((MqttAsyncClient) mqttClient).setBufferOpts(disconnectedBufferOptions);
        mqttClient.setCallback(new OnMqttCallBack(log, this, collectBiz));  // 设置mqttClient的回调
        // 初始化连接
        connect();
    }

    /**
     * 获得 MqttPahoClientFactory
     *
     * @return MqttPahoClientFactory
     */
    @Bean
    public MqttPahoClientFactory clientFactory() {
        final DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        factory.setConnectionOptions(options);
        factory.setPersistence(persistence);
        return factory;
    }

    /**
     * mqttclent连接
     */
    public void connect() {
        executorService.submit(() -> {// 连接关闭都用一个单独的线程控制
            try {
                mqttClient.connect(options);
            } catch (MqttException e) {
                log.error("mqtt客户端启动连接失败");
                e.printStackTrace();
            }
        });
    }

    /**
     * 订阅主题,订阅的时候进行连接
     *
     * @param topics 主题
     * @throws MqttException
     */
    public void subscribe(String topics) throws MqttException {
        mqttClient.subscribe(topics, qos);
    }

    /**
     * 获得单例的mqqt连接
     *
     * @return IMqttAsyncClient
     */
    @Bean
    public IMqttAsyncClient getMqqtClient() {
        if (mqttClient == null) {
            synchronized (MqttConfig.class) {
                if (mqttClient == null) {
                    try {
                        setMqttClient();
                    } catch (MqttException e) {
                        log.error("设置mqqtClient失败");
                    }
                }
            }
        }

        return mqttClient;
    }

    /**
     * 设置mqttClient
     *
     * @throws MqttException
     */
    private void setMqttClient() throws MqttException {
        this.mqttClient = clientFactory().getAsyncClientInstance(brokerUrl, clientId);
    }

    /**
     * 关闭mqtt连接
     */
    @Override
    @PreDestroy
    public void close() {
        if (this.mqttClient != null && this.mqttClient.isConnected()) {
            executorService.submit(() -> {
                try {
                    log.info("关闭mqqt连接");
                    mqttClient.disconnect();
                    mqttClient.close();
                } catch (MqttException e) {
                    log.error("关闭mqqt连接失败");
                    e.printStackTrace();
                }
            });
        }
    }
}

回调类

package cm.soft.collect.service;

import cm.soft.collect.config.LogConfig;
import cm.soft.collect.config.MqttConfig;
import cm.soft.collect.biz.CollectBiz;
import cm.soft.collect.threadUtil.CustomTaskThreads;
import cm.soft.collect.threadUtil.CustomThread;
import lombok.SneakyThrows;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.stereotype.Component;

/**
 * emq回调类
 */
@Component
public class OnMqttCallBack implements MqttCallbackExtended {

    private final LogConfig log;
    private final MqttConfig mqttConfig;
    private final CollectBiz collectBiz;
    static CustomThread messageArrivedThread = (CustomThread) CustomTaskThreads.MessageArrivedThtead;

    public OnMqttCallBack(final LogConfig log, final MqttConfig mqttConfig, final CollectBiz collectBiz) {
        this.log = log;
        this.mqttConfig = mqttConfig;
        this.collectBiz = collectBiz;
    }

    @Override
    public void connectionLost(Throwable throwable) {
        log.error("连接丢失" + throwable.getMessage());
        mqttConfig.connect();
    }

    @Override
    public void messageArrived(String topic, MqttMessage mqttMessage) {
        messageArrivedThread.setOnceWork(() -> {
            collectBiz.saveDataToSql(topic, mqttMessage);
        });

        // 模拟同步代码,代表比较耗时的任务,最终会丢失连接,同步的方法必须在处理同步代码之后才能得到下一个消息,
        // 得到消息的时间就会变很长,会导致大量消息的堆积,报Eof
//        for(int i=0;i<1000000000;i++){
//
//        }
    }

    /**
     * 交付完成回调。在publish消息的时候会收到此回调.
     * qos:
     * 0 发送完则回调 最多一次传送 (只负责传送,发送过后就不管数据的传送情况)
     * 1 至少一次传送 (确认数据交付) 会在对方收到时候回调
     * 2 正好一次传送 (保证数据交付成功) 会在对方收到时候回调
     *
     * @param iMqttDeliveryToken
     */
    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        iMqttDeliveryToken.isComplete();
    }

    /**
     * 连接完成回调
     *
     * @param reconnect true 断开重连,false 首次连接
     * @param serverURI 服务器URI
     */
    @SneakyThrows
    @Override
    public void connectComplete(boolean reconnect, String serverURI) {
        if (!reconnect) {
            log.info("mqtt客户端连接成功");
        } else {
            log.info("mqtt客户端重新连接成功");
        }

        // 连接完成进行订阅
        collectBiz.subscribe();
    }
}

业务类

package cm.soft.collect.biz;

import cm.soft.collect.config.MqttConfig;
import cm.soft.collect.threadUtil.CustomThreadPoolFactory;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.ExecutorService;

@Component
public class CollectBiz {

    @Autowired
    MqttConfig mqttConfig;

    @Autowired
    MachineCurrentProcessBizState machineCurrentProcessForVersionBizState;

    @Autowired
    MachineProcessOnChangedBizState machineProcessOnChangedBizState;


    /**
     * 先进行订阅具体的主题
     *
     * @throws MqttException
     */
    public void subscribe() throws MqttException {
        mqttConfig.subscribe("V_2/+/+/+/+/+/+/+/+/+");
    }

    public void saveDataToSql(String topic, MqttMessage mqttMessage) {
        BizType bizType = BizType.filterCollectType(topic);

        if (bizType != null) {
            if (bizType.equals(BizType.SAVE_MACHINE_PROCESS_ON_CHANGED_TOSQL)) {
                machineProcessOnChangedBizState.saveDataToSql(topic, mqttMessage);
            } else if (bizType.equals(BizType.SAVE_MACHINE_CURRENT_PROCESS_FOR_VERSION_TOSQL)) {
                machineCurrentProcessForVersionBizState.saveDataToSqlOnRequest(topic, mqttMessage);
            }
        }

    }

}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值