什么是MQTT
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)作为一款发布(pub)/订阅(sub)模式的"轻量级"通讯协议,凭借其轻量、简单、开放和易于实现等优点,在物联网领域得到了广泛应用。
在这里我们是基于CentOS7 来进行搭建的
# 1. 下载
wget https://www.emqx.com/en/downloads/broker/5.0.6/emqx-5.0.6-el7-arm64.rpm
# 2. 安装
sudo yum install emqx-5.0.6-el7-arm64.rpm
# 3. 运行
sudo emqx start
下载
安装
选择y
开始
这里要记住,我们如果是自己的虚拟机时我们要在防火墙中开启-- 1883,8083,8084,8883,18083这几个端口,同样是要云服务取就要配置这几个端口
安装完成后就是可以访问 服务器IP地址+18083 这个地址就好可以看到这样的 默认的账号:admin 密码:public
在客户端中是能够看到我们已经链接到的客户端的
做测试的话我们可以下载一个工具 MQTTX
具体使用
MQTT 整合SpringBoot
所需依赖
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.2</version>
</dependency>
MqttConfig.java 用于获取客户端配置
import com.hai.cardu.vo.MqttClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Data
@Configuration
@ConfigurationProperties(prefix = "customer.mqtt")
public class MqttConfig {
String broker;
List<MqttClient> clientList;
}
MqttClient.java 用户存储客户端的参数
import lombok.Data;
@Data
public class MqttClient {
private String clientId;
private String subscribeTopic;
private String userName;
private String password;
}
MqttClientCreate.java 用于创建客户端
package com.hai.cardu.myMqtt;
import com.hai.cardu.config.MqttConfig;
import com.hai.cardu.vo.MqttClientVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;
@Component
@Slf4j
public class MqttClientCreate {
@Resource
private MqttClientManager MqttClientManager;
@Autowired
private MqttConfig mqttConfig;
@PostConstruct
public void createMqttClient() {
List<MqttClientVO> mqttClientList = mqttConfig.getClientList();
for (MqttClientVO mqttClient : mqttClientList) {
log.info("{}",mqttClient);
MqttClientManager.createMqttClient(mqttClient.getClientId(), mqttClient.getSubscribeTopic(), mqttClient.getUserName(), mqttClient.getPassword());
}
}
}
MqttClientManager.java 管理客户端操作,进行创建客户端,让客户端订阅主题接收消息
import lombok.extern.slf4j.Slf4j;
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.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@Component
public class MqttClientManager {
@Value("${customer.mqtt.broker}")
private String mqttBroker;
@Resource
private MqttCallBackContext mqttCallBackContext;
public static Map<String, MqttClient> MQTT_CLIENT_MAP = new ConcurrentHashMap<>();
public static MqttClient getMqttClientById(String clientId) {
return MQTT_CLIENT_MAP.get(clientId);
}
public void createMqttClient(String clientId, String subscribeTopic, String userName, String password) {
MemoryPersistence persistence = new MemoryPersistence();
try {
MqttClient client = new MqttClient(mqttBroker, clientId, persistence);
MqttConnectOptions connOpts = new MqttConnectOptions();
if (null != userName && !"".equals(userName)) {
connOpts.setUserName(userName);
}
if (null != password && !"".equals(password)) {
connOpts.setPassword(password.toCharArray());
}
connOpts.setCleanSession(true);
if (null != subscribeTopic && !"".equals(subscribeTopic)) {
AbsMqttCallBack callBack = mqttCallBackContext.getCallBack(clientId);
if (null == callBack) {
callBack = mqttCallBackContext.getCallBack("default");
}
callBack.setClientId(clientId);
callBack.setConnectOptions(connOpts);
client.setCallback(callBack);
}
client.connect(connOpts);
if (null != subscribeTopic && !"".equals(subscribeTopic)) {
if (subscribeTopic.contains("-"))
client.subscribe(subscribeTopic.split("-"));
else
client.subscribe(subscribeTopic);
}
MQTT_CLIENT_MAP.putIfAbsent(clientId, client);
} catch (MqttException e) {
log.error("Create mqttClient failed!", e);
}
}
}
MqttCallBackContext.java 客户端订阅消息环境配置,以那种方式回调
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
@Slf4j
public class MqttCallBackContext {
private final Map<String, AbsMqttCallBack> callBackMap = new ConcurrentHashMap<>();
public MqttCallBackContext(Map<String, AbsMqttCallBack> callBackMap) {
this.callBackMap.clear();
callBackMap.forEach((k, v) -> this.callBackMap.put(k, v));
}
public AbsMqttCallBack getCallBack(String clientId) {
return this.callBackMap.get(clientId);
}
}
AbsMqttCallBack.java 接收消息的回调处理抽象类
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.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttMessage;
@Slf4j
public abstract class AbsMqttCallBack implements MqttCallback {
private String clientId;
private MqttConnectOptions connectOptions;
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public MqttConnectOptions getConnectOptions() {
return connectOptions;
}
public void setConnectOptions(MqttConnectOptions connectOptions) {
this.connectOptions = connectOptions;
}
@Override
public void connectionLost(Throwable throwable) {
try {
if (null != clientId) {
if (null != connectOptions) {
MqttClientManager.getMqttClientById(clientId).connect(connectOptions);
} else {
MqttClientManager.getMqttClientById(clientId).connect();
}
}
} catch (Exception e) {
log.error("{} reconnect failed!", e);
}
}
@Override
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
String content = new String(mqttMessage.getPayload());
handleReceiveMessage(topic, content);
}
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
log.info("消息发送成功");
}
protected abstract void handleReceiveMessage(String topic, String message);
}
DefaultMqttCallBack.java 消息回调处理类
import com.google.gson.Gson;
import com.hai.cardu.vo.VisitorsRecord;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@Slf4j
@Component("default")
public class DefaultMqttCallBack extends AbsMqttCallBack {
@Override
protected void handleReceiveMessage(String topic, String message) {
log.info("接收到消息---{}", message);
}
MqttClientUtil.java 发送消息工具类
import com.hai.cardu.myMqtt.MqttClientManager;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
@Slf4j
public class MqttClientUtil {
public static void sendMqttMsg(String clientId, String topic, String content) {
try {
MqttMessage message = new MqttMessage(content.getBytes());
message.setQos(2);
MqttClient mqttClient = MqttClientManager.getMqttClientById(clientId);
if (null == mqttClient) {
log.error("Not exist mqttClient where it's clientId is {}", clientId);
return;
}
MqttClientManager.getMqttClientById(clientId).publish(topic, message);
log.info("Publish to mqtt broker,message={}", message);
} catch (MqttException e) {
log.error("MqttClient send msg faild!",e);
}
}
}
application.yml
server:
port: 8080
customer:
mqtt:
broker: tcp://服务器IP:端口号
clientList:
- clientId: nxys_service
subscribeTopic: mqtt/printer-mqtt/face/JWJA220308396/Rec
username: admin
password: admin111
这里我们配置完后就可以通过使用MqttClientUtil 类中的sendMqttMsg方法去发送消息测试了
|