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;
	}
}

有问题的,欢迎指出。

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