Mqtt集成Spring,解決callBack重連之後訂閱消息失敗的問題

MqttCallback接口裏面只有個3方法

public interface MqttCallback {
    void connectionLost(Throwable var1);

    void messageArrived(String var1, MqttMessage var2) throws Exception;

    void deliveryComplete(IMqttDeliveryToken var1);
}

connectionLost是在連接已經連上且丟失後走這裏
messageArrived這個是消息發送到接收端時觸發
deliveryComplete這個是發送完成

 

MqttCallbackExtended是繼承了MqttCallback

public interface MqttCallbackExtended extends MqttCallback {
    void connectComplete(boolean var1, String var2);
}

這個方法表示,丟失重連成功後會觸發。

廢話不多說,直接上代碼。

pom.xml中添加

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

消息接收端:MqttConsumers.java

package com.mqtt;

import javax.annotation.Resource;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttSecurityException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.stereotype.Component;

import com.dlysapie.mqtt.bo.ReceiveMsg;
import com.tenet.util.DateUtil;

/**
 * 消息接收端
 * 
 * @author libaibai
 * @version 1.0 2020年3月17日
 */
@Component
public class MqttConsumers implements MqttCallbackExtended {

	private static final Logger LOG = LogManager.getLogger(MqttConsumers.class);

	public static final String HOST = "tcp://rmqtt-test.xxx.cn:1883";
	public static final String TOPIC = "SmartMeter/server/#"; // 訂閱主題
	private static final String clientid = "client";
	private MqttClient client;
	private MqttConnectOptions options;
	// private String userName = "test";
	// private String passWord = "test";

	@Resource
	public ReceiveMsg receiveMsg;

	public MqttConsumers() {
		connect();
	}

	// 連接
	private void connect() {
		try {
			if (client == null) {
				// host爲主機名,test爲clientid即連接MQTT的客戶端ID,一般以客戶端唯一標識符表示,MemoryPersistence設置clientid的保存形式,默認爲以內存保存
				client = new MqttClient(HOST, clientid, new MemoryPersistence());
			}
			// MQTT的連接設置
			options = new MqttConnectOptions();
			// 設置是否清空session,這裏如果設置爲false表示服務器會保留客戶端的連接記錄,這裏設置爲true表示每次連接到服務器都以新的身份連接
			options.setCleanSession(true);
			// 設置連接的用戶名
			// options.setUserName(userName);
			// 設置連接的密碼
			// options.setPassword(passWord.toCharArray());
			// 設置超時時間 單位爲秒
			options.setConnectionTimeout(10);
			// 設置會話心跳時間 單位爲秒 服務器會每隔1.5*20秒的時間向客戶端發送個消息判斷客戶端是否在線,但這個方法並沒有重連的機制
			options.setKeepAliveInterval(20);
			// mqttClient.reconnect(); 方法會判斷這個參數
			options.setAutomaticReconnect(true);

			// 設置回調
			client.setCallback(this);
			// MqttTopic topic = client.getTopic(TOPIC);
			// setWill方法,如果項目中需要知道客戶端是否掉線可以調用該方法。設置最終端口的通知消息
			// options.setWill(topic, "close".getBytes(), 0, true);
			client.connect(options);
			// 訂閱消息
			int[] Qos = { 1 };
			String[] topic1 = { TOPIC };
			client.subscribe(topic1, Qos);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void disconnect() {
		try {
			client.disconnect();
		} catch (MqttException e) {
			e.printStackTrace();
		}
	}

	// 重新鏈接
	public void startReconnect() {
		if (!client.isConnected()) {
			try {
				client.connect();
			} catch (MqttSecurityException e) {
				e.printStackTrace();
			} catch (MqttException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public void connectionLost(Throwable cause) {
		LOG.info("連接斷開,正在重新連接...:");
		startReconnect();
		LOG.info("重新連接成功");
	}

	@Override
	public void messageArrived(String topic, MqttMessage message) throws Exception {
		// subscribe後得到的消息會執行到這裏面
		System.out.println("接收消息主題:" + topic);
		// System.out.println("接收消息Qos:" + message.getQos());
		String payload = new String(message.getPayload());
		System.out.println("接收消息內容:" + payload + " , " + DateUtil.getTimeStampToDate(DateUtil.getTimeStampLong()));
        // 這裏是業務處理代碼
		receiveMsg.exe(topic, payload);
	}

	@Override
	public void deliveryComplete(IMqttDeliveryToken token) {
		// TODO Auto-generated method stub
		System.out.println("deliveryComplete---------" + token.isComplete());
	}

	@Override
	public void connectComplete(boolean reconnect, String serverURI) {
		// 連接成功後調用
		int[] Qos = { 1 };
		String[] topic1 = { TOPIC };
		try {
			client.subscribe(topic1, Qos);
		} catch (MqttException e) {
		} // 具體訂閱代碼
	}

	public static void main(String[] args) throws MqttException {
		MqttConsumers client = new MqttConsumers();
		client.connect();
	}
}

消息發佈端:MqttPublisher.java

package com.mqtt;

import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

/**
 * 發送消息服務類
 * 
 * @author libaibai
 * @version 1.0 2020年3月17日
 */
@Component
public class MqttPublisher {

	public static final String HOST = "tcp://rmqtt-test.xxxx:1883";
	private static final String clientid = "server";

	@Bean("mqttClient")
	public MqttClient connect() throws MqttException {
		MemoryPersistence persistence = new MemoryPersistence();
		MqttConnectOptions connOpts = new MqttConnectOptions();
		connOpts.setCleanSession(true);
		connOpts.setConnectionTimeout(10);// 設置超時時間
		connOpts.setKeepAliveInterval(20);// 設置會話心跳時間
		// String[] uris = {"tcp://10.100.124.206:1883","tcp://10.100.124.207:1883"};
		// connOpts.setServerURIs(uris); //起到負載均衡和高可用的作用
		MqttClient mqttClient = new MqttClient(HOST, clientid, persistence);
		mqttClient.connect(connOpts);
		return mqttClient;
	}
}

消息發佈業務處理:PushlishMsg.java

package com.mqtt.bo;

import java.util.Arrays;

import javax.annotation.Resource;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttPersistenceException;
import org.springframework.stereotype.Component;

import com.dlysapie.mqtt.MqttPublisher;
import com.dlysapie.mqtt.util.AesUtils;
import com.dlysapie.mqtt.util.CommUtil;

/**
 * 命令發送類
 * 
 * @author libaibai
 * @version 1.0 2020年3月20日
 */
@Component
public class PublishMsg {

	private static final Logger LOG = LogManager.getLogger(PublishMsg.class);

	// 發佈主題
	public static final String topic = "SmartMeter/device/ce1f5bdbc4494f4db5194e3a1c30ab00/register";

	@Resource
	public MqttClient mqttClient;

	// 發送配置aes祕鑰
	public void sendAesKey() {
		byte cmd = 3;
		byte[] pudDateByte = AesUtils.AESKEY.getBytes();

		// 添加類型屬性
		byte[] pudDateType = { 16, (byte) AesUtils.AESKEY.length() };
		byte[] payload = CommUtil.getPayLoad(cmd, ArrayUtils.addAll(pudDateType, pudDateByte));
		System.out.println("發送祕鑰原始數據(base64轉碼)" + Arrays.toString(payload));
		try {
			mqttClient.publish(topic, getMessage(payload));
		} catch (MqttPersistenceException e) {
			e.printStackTrace();
		} catch (MqttException e) {
			e.printStackTrace();
		}
	}


	/**
	 * 得到發送的message
	 * 
	 * @param payload 消息字節數組
	 * @return
	 */
	public MqttMessage getMessage(byte[] payload) {
		MqttMessage message = new MqttMessage();
		message.setQos(1);
		message.setRetained(true);
		message.setPayload(payload);
		return message;
	}
}

有問題的,歡迎指出。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章