SpringBoot 結合官網對MQTT訊息佇列整合記錄

菜菜920發表於2024-07-25

SpringBoot 結合官網對MQTT訊息佇列整合

首先是 maven Pom 的引入 Mqtt Client

        <dependency>
            <groupId>org.eclipse.paho</groupId>
            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
            <version>1.2.2</version>
        </dependency>

其次編寫一個Mqtt回撥方法類 去實現 MqttCallback 介面 用於訊息的接收


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 java.util.Base64;

/**
 * @author caicai
 *
 *
 * 訊息回撥顯示
 */
@Slf4j
public class PushCallback implements MqttCallback {

    /**
     * 連線丟失
     * @param throwable
     */
    @Override
    public void connectionLost(Throwable throwable) {

    }
    /**
     * 訊息到達
     * @param s
     * @param mqttMessage
     * @throws Exception
     */

    @Override
    public void messageArrived(java.lang.String s, MqttMessage mqttMessage) throws Exception {
        log.info("com.kxcd.testkfka.mqtt.tools.PushCallback.messageArrived===>接收到topic {} ",s);
        byte[] payload = mqttMessage.getPayload();
        String s1 = Base64.getEncoder().encodeToString(payload);
        log.info("PushCallback.messageArrived===>接收到訊息內容 {} ",mqttMessage);
    }



    /**
     * 訊息傳送完成
     * @param iMqttDeliveryToken
     */
    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {

    }
}

為了程式碼的美觀,這裡寫死配置,都定義的常量,如果真正使用的話,建議這裡修改成 讀取配置方式 例如 nacos

/**
 * @author caicai
 */
public class MqConfigConstant {

    public class MqClientConfig {
        // 使用者名稱稱
        public static final String MQ_USER_NAME = "test";
        // 使用者密碼
        public static final String MQ_PASS_WORD = "test";
        // 預設主題
        public static final String MQ_DEFAULT_TOPIC = "test";
        // 客戶端ID
        public static final String MQ_CLIENT_ID = "TEST_MQ";
        // 連線地址
        public static final String MQ_CONNECT_URL = "tcp://47.102.199.23:1883";

    }
    public class ConstantNumber {
        // 預設訊息質量
        public static final int MQ_QOS1 = 1;
    }
}

編寫一個初始化配置類

這裡本來是打算使用單例的模式進行配置的,寫了一個單例的工具類,後面覺得這樣方式 很麻煩 ,於是決定 修改成一次性初始化的

package com.xx.xx.mqtt.config;

import com.xx.xx.constant.MqConfigConstant;
import com.xxx.xx.mqtt.xx.PushCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

/**
 * @author caicai
 */

@Component
public class MqClientConfig {

    private  MqttClient mqttClientInit;
    @Bean
    public MqttClient getMqttClient() {
        // 首先判斷一下是否已經初始化過,如果已經初始化過,則直接返回
        if(mqttClientInit == null){
            synchronized (MqClientConfig.class){
                if(mqttClientInit == null){
                    try {
                        MemoryPersistence persistence = new MemoryPersistence();
                        MqttClient client = new MqttClient(MqConfigConstant.MqClientConfig.MQ_CONNECT_URL, MqConfigConstant.MqClientConfig.MQ_CLIENT_ID, persistence);
                        // 設定連線時協帶引數
                        MqttConnectOptions connOpts = new MqttConnectOptions();
                        //  設定連線時候需要用的使用者名稱和密碼
                        connOpts.setUserName(MqConfigConstant.MqClientConfig.MQ_USER_NAME);
                        connOpts.setPassword(MqConfigConstant.MqClientConfig.MQ_PASS_WORD.toCharArray());
                        // 連線
                        client.connect(connOpts);
                        // 呼叫之前的回撥方法類
                        client.setCallback(new PushCallback());
                        // 設定預設訂閱 -這裡我為了方便測試,加的。可以去掉
                        client.subscribe(MqConfigConstant.MqClientConfig.MQ_DEFAULT_TOPIC);
                        mqttClientInit = client;
                    }catch (Exception e){
                        System.out.println("初始化MqttClient失敗");
                    }
                }
            }
        }
        return mqttClientInit;
    }
}

寫提供實現服務,來方便後續的呼叫 例如跨服務呼叫

@Service
public class MqttService {
    @Resource
   private MqttClient mqttClient;
    public void setSubscribe(String subTopic) throws MqttException {
        mqttClient.subscribe(subTopic);
    }
    public void  setPublish(String pubTopic,String msg) throws MqttException {
        MqttMessage message = new MqttMessage(msg.getBytes());
        mqttClient.publish(pubTopic,message);
    }
    public void setPublish(String pubTopic,String msg,int qos) throws MqttException {
        MqttMessage message = new MqttMessage(msg.getBytes());
        message.setQos(qos);
        mqttClient.publish(pubTopic,message);
    }

}

總結 :一個主題可以多個客戶端訂閱,如果推送訊息給這個主題裡,兩個客戶端都會收到相關訊息。其次客戶端可以訂閱,也可傳送。

相關文章