import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import lombok.Data;
import lombok.ToString;
/**
* MQTT平台配置
*
**/
@Data
@ToString
@Configuration
@ConfigurationProperties(prefix = "xx.mqtt")
public class XxMqttConfig {
/**
* MQTT平台host IP and PORT
**/
private String host = "tcp://192.168.10.199:1883";
/**
* MQTT-username
**/
private String username = "xxxxx";
/**
* MQTT-password
**/
private String password = "xxxxx";
/**
* 订阅主题的客户端ID
*/
private String clientId = "xxxxx-dl-client";
private String sendId = "xxxx-dl-send";
/**
* 主题集合
*/
private String topics = "testtopic/#,1";
private Integer timeout = 100;
private Integer keepalive = 20;
/**
* QoS0 代表,Sender 发送的一条消息,Receiver 最多能收到一次,也就是说 Sender 尽力向 Receiver 发送消息,如果发送失败,也就算了;
* QoS1 代表,Sender 发送的一条消息,Receiver 至少能收到一次,也就是说 Sender 向Receiver 发送消息,如果发送失败,会继续重试,直到 Receiver 收到消息为止,但是因为重传的原因,Receiver 有可能会收到重复的消息;
* QoS2 代表,Sender 发送的一条消息,Receiver 确保能收到而且只收到一次,也就是说 Sender 尽力向 Receiver发送消息,如果发送失败,会继续重试,直到 Receiver 收到消息为止,同时保证 Receiver 不会因为消息重传而收到重复的消息。
*
*/
private Integer qos = 2;
/**
* MQTT开关
*/
private Boolean open = false;
}
import java.util.Arrays;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
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.Configuration;
import com.aliyun.openservices.shade.com.alibaba.fastjson.JSON;
import com.xxx.xxx.xxx.xxx.config.DhMqttConfig;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Configuration
public class XxttConsumerConfig {
@Resource
private XxMqttConfig mqtt;
/**
* 客户端对象
*/
private MqttClient client;
/**
* 在bean初始化后连接到服务器
*/
@PostConstruct
private void init() {
if (mqtt.getOpen()) {//开关控制
if (connect(mqtt.getHost(), mqtt.getClientId()))
log.info("订阅者:" + mqtt.getClientId() + "成功连接到:" + mqtt.getHost() + "MQTT服务SUCCESS");
subscribeDefaultTopic();
}
}
/**
* 客户端连接服务端
*/
private Boolean connect(String host, String clientId) {
try {
// 创建MQTT客户端对象
client = new MqttClient(host, clientId, new MemoryPersistence());
// 设置回调
client.setCallback(new MqttConsumerCallBack());
client.connect(setOptions());
return true;
} catch (MqttException e) {
e.printStackTrace();
}
return false;
}
/**
* 连接设置
*
* @return
*/
private MqttConnectOptions setOptions() {
MqttConnectOptions options = new MqttConnectOptions();
// 是否清空session,设置为false表示服务器会保留客户端的连接记录,客户端重连之后能获取到服务器在客户端断开连接期间推送的消息
// 设置为true表示每次连接到服务端都是以新的身份
options.setCleanSession(true);
// 设置连接用户名
options.setUserName(mqtt.getUsername());
// 设置连接密码
options.setPassword(mqtt.getPassword().toCharArray());
// 设置超时时间,单位为秒
options.setConnectionTimeout(mqtt.getTimeout());
// 设置心跳时间 单位为秒,表示服务器每隔1.5*20秒的时间向客户端发送心跳判断客户端是否在线
options.setKeepAliveInterval(mqtt.getKeepalive());
options.setAutomaticReconnect(true);
// 设置遗嘱消息的话题,若客户端和服务器之间的连接意外断开,服务器将发布客户端的遗嘱信息
options.setWill("willTopic", (mqtt.getClientId() + "与服务器断开连接").getBytes(), 0, false);
return options;
}
/**
* 消息等级,和主题数组一一对应,服务端将按照指定等级给订阅了主题的客户端推送消息 String[] topics = { "topic1","topic2"
* };int[] qos = { 1, 1 }; 订阅默认主题
*/
public void subscribeDefaultTopic() {
// 默认主题
List<String> topicList = Arrays.asList(mqtt.getTopics().trim().split(","));
String[] topics = new String[topicList.size()];
topicList.toArray(topics);
int[] qos = new int[topicList.size()];
for (int i = 0; i < topics.length; i++) {
qos[i] = mqtt.getQos();
}
try {
// 订阅主题
client.subscribe(topics, qos);
} catch (MqttException e) {
e.printStackTrace();
}
log.info("正在订阅默认主题列表:" + JSON.toJSONString(topics) + "===对应Qos列表:" + JSON.toJSONString(qos) + "===SUCCESS");
}
/**
* 断开连接
*/
public void disConnect() {
try {
client.disconnect();
} catch (MqttException e) {
e.printStackTrace();
}
}
/**
* 订阅主题
*/
public void subscribe(String topic, int qos) {
try {
client.subscribe(topic, qos);
} catch (MqttException e) {
e.printStackTrace();
}
}
}
=========================================================================================
import javax.annotation.Resource;
import org.eclipse.paho.client.mqttv3.IMqttAsyncClient;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.context.annotation.Configuration;
import com.xxx.xxx.xxxx.xxxx.config.DhMqttConfig;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Configuration
public class MqttConsumerCallBack implements MqttCallback {
@Resource
private XxMqttConfig mqtt;
/**
* 客户端断开连接的回调
*/
@Override
public void connectionLost(Throwable throwable) {
log.info(mqtt.getClientId() + "与服务器断开连接,可重连");
}
/**
* 消息到达的回调
*/
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
// 这里可以处理接收的数据
log.info("\n----------------------------START---------------------------\n" +
"接收到订阅消息:\ntopic:" + topic + "\nmessage:" + new String(message.getPayload()) +
"\n-----------------------------END----------------------------");
// log.info(String.format("接收消息主题 : %s", topic));
// log.info(String.format("接收消息Qos : %d", message.getQos()));
// log.info(String.format("接收消息内容 : %s", new String(message.getPayload())));
// log.info(String.format("接收消息retained : %b", message.isRetained()));
}
/**
* 消息发布成功的回调
*/
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
IMqttAsyncClient client = iMqttDeliveryToken.getClient();
log.info(client.getClientId() + "接收消息成功!");
}
}
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.context.annotation.Configuration;
import com.xxx.xxxx.xxx.xxx.config.DhMqttConfig;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Configuration
public class MqttProviderConfig {
@Resource
private XxMqttConfig mqtt;
/**
* 客户端对象
*/
private MqttClient client;
/**
* 在bean初始化后连接到服务器
*/
@PostConstruct
private void init() {
if (mqtt.getOpen()) {//开关控制
if (connect(mqtt.getHost(), mqtt.getSendId()))
log.info("提供者:" + mqtt.getSendId() + "成功连接到:" + mqtt.getHost() + "MQTT服务SUCCESS");
}
}
/**
* 客户端连接服务端
*/
private Boolean connect(String host, String sendId) {
try {
// 创建MQTT客户端对象
client = new MqttClient(host, sendId, new MemoryPersistence());
// 设置回调
client.setCallback(new MqttProviderCallBack());
client.connect(setOptions());
return true;
} catch (MqttException e) {
e.printStackTrace();
}
return false;
}
/**
* 连接设置
*
* @return
*/
private MqttConnectOptions setOptions() {
MqttConnectOptions options = new MqttConnectOptions();
// 是否清空session,设置false表示服务器会保留客户端的连接记录(订阅主题,qos),客户端重连之后能获取到服务器在客户端断开连接期间推送的消息
// 设置为true表示每次连接服务器都是以新的身份
options.setCleanSession(true);
// 设置连接用户名
options.setUserName(mqtt.getUsername());
// 设置连接密码
options.setPassword(mqtt.getPassword().toCharArray());
// 设置超时时间,单位为秒
options.setConnectionTimeout(mqtt.getTimeout());
// 设置心跳时间 单位为秒,表示服务器每隔 1.5*20秒的时间向客户端发送心跳判断客户端是否在线
options.setKeepAliveInterval(mqtt.getKeepalive());
options.setAutomaticReconnect(true);
// 设置遗嘱消息的话题,若客户端和服务器之间的连接意外断开,服务器将发布客户端的遗嘱信息
options.setWill("willTopic", (mqtt.getSendId() + "与服务器断开连接").getBytes(), 0, false);
return options;
}
/**
* 发布
*
* @param qos
* @param retained
* @param topic
* @param message
*/
public void publish(int qos, boolean retained, String topic, String message) {
MqttMessage mqttMessage = new MqttMessage();
mqttMessage.setQos(qos);
//消息保留机制,若设置为true,mqtt服务器会保留每次发布的消息,若订阅某主题的客户端重启,则会把此主题之前发布的消息重新推送到客户端。
mqttMessage.setRetained(retained);
mqttMessage.setPayload(message.getBytes());
// 主题的目的地,用于发布/订阅信息
MqttTopic mqttTopic = client.getTopic(topic);
// 提供一种机制来跟踪消息的传递进度
// 用于在以非阻塞方式(在后台运行)执行发布是跟踪消息的传递进度
MqttDeliveryToken token;
try {
// 将指定消息发布到主题,但不等待消息传递完成,返回的token可用于跟踪消息的传递状态
// 一旦此方法干净地返回,消息就已被客户端接受发布,当连接可用,将在后台完成消息传递。
token = mqttTopic.publish(mqttMessage);
token.waitForCompletion();
} catch (MqttException e) {
e.printStackTrace();
}
}
}
===================================================================================
import javax.annotation.Resource;
import org.eclipse.paho.client.mqttv3.IMqttAsyncClient;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.context.annotation.Configuration;
import com.xxx.xxx.xxx.xxx.config.DhMqttConfig;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Configuration
public class MqttProviderCallBack implements MqttCallback {
@Resource
private DhMqttConfig mqtt;
/**
* 与服务器断开的回调
*/
@Override
public void connectionLost(Throwable cause) {
log.info(mqtt.getSendId() + "与服务器断开连接");
}
/**
* 消息到达的回调
*/
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
log.info("\n----------------------------START---------------------------\n" +
"发送的订阅消息:\ntopic:" + topic + "\nmessage:" + new String(message.getPayload()) +
"\n-----------------------------END----------------------------");
}
/**
* 消息发布成功的回调
*/
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
IMqttAsyncClient client = token.getClient();
log.info(client.getClientId() + "发布消息成功!");
}
}