SpringBoot+MQTT协议+Maven
文章目录
前言
MQTT(Message Queuing Telemetry Transport)是基于二进制消息的发布/订阅编程模式的消息协议,非常适合需要低功耗和网络带宽有限的IoT场景。这里整理关于mqtt在springboot中集成使用。
提示:以下是本篇文章正文内容,下面案例可供参考
一、maven依赖
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.2</version>
</dependency>
二、自定义Springboot的yml配置文件以及相关配置类
1.配置YML
代码如下(示例):
server:
tomcat:
uri-encoding: UTF-8
max-threads: 1000
min-spare-threads: 30
port: 8080
connection-timeout: 5000
#mqtt服务
mqtt:
host: "tcp://xxxx:1883" #MQTT服务地址和断开
serverClientId: "iot"
user: "admin"
pwd: "admin"
三、MQTT工具类
1.MQTT工具类Java代码
/**
* MQTT工具类
*
* @author SongWei
*/
@Service
@Slf4j
public class MqttUtils {
@Value("${mqtt.host}")
private String host;
@Value("${mqtt.serverClientId}")
private String serverClientId;
@Value("${mqtt.user}")
private String user;
@Value("${mqtt.pwd}")
private String pwd;
/**
* 订阅主题
*/
public boolean subscribe(String theme) {
try {
if (StrUtil.isEmpty(theme)) {
theme = TopicEnum.DEFAULT.getName();
}
//MQTT的连接设置
MqttClient client = new MqttClient(host, serverClientId, new MemoryPersistence());
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(Constants.CLEAN_SESSION);
options.setUserName(user);
options.setPassword(pwd.toCharArray());
options.setConnectionTimeout(Constants.CONNECTION_TIMEOUT);
options.setKeepAliveInterval(Constants.KEEP_ALIVE_INTERVAL);
//设置断开后重新连接
options.setAutomaticReconnect(true);
//设置回调
client.setCallback(new PushCallback());
MqttTopic topic = client.getTopic(theme);
//如项目中需要知道客户端是否掉线可以调用该方法。设置最终端口的通知消息
options.setWill(topic, Constants.WILL_PAYLOAD, Constants.QOS, true);
client.connect(options);
int[] qos = {Constants.QOS};
String[] topic1 = {theme};
client.subscribe(topic1, qos);
return true;
} catch (Exception e) {
log.error("推送消息--异常\nclientId:{}\nexception:{}", serverClientId, e.toString());
return false;
}
}
/**
* 推送消息
*/
public boolean pushMsg(String clientId, String theme, String msg) {
if (StrUtil.isEmpty(theme)) {
theme = TopicEnum.DEFAULT.getName();
}
MqttTopic connect = this.getTopic(clientId, theme);
MqttMessage message = new MqttMessage();
//保证消息能到达一次
message.setQos(1);
message.setRetained(true);
//String str = "{\"msg\":\"" + msg + "\"}";
message.setPayload(msg.getBytes());
try {
this.publish(connect, message);
return true;
} catch (Exception e) {
log.error("推送消息--异常\nclientId:{}\nexception:{}", clientId, e.toString());
return false;
}
}
/**
* 获取订阅
*/
private MqttTopic getTopic(String clientId, String theme) {
MqttClient mqttClient = this.mqttClient(clientId);
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(false);
options.setUserName(user);
options.setPassword(pwd.toCharArray());
// 设置超时时间
options.setConnectionTimeout(10);
// 设置会话心跳时间
options.setKeepAliveInterval(20);
try {
mqttClient.setCallback(new PushCallback());
mqttClient.connect(options);
return mqttClient.getTopic(theme);
} catch (Exception e) {
log.error("获取订阅--异常\nclientId:{}\ntheme:{}\nexception:{}", clientId, theme, e.toString());
}
return null;
}
/**
* 连接mqtt服务
*/
private MqttClient mqttClient(String clientId) {
MqttClient mqttClient = null;
try {
mqttClient = new MqttClient(host, clientId, new MemoryPersistence());
} catch (MqttException e) {
log.error("连接MQTT服务器--异常\nclientId:{}\nexception:{}", clientId, e.toString());
}
return mqttClient;
}
/**
* 推送消息
*/
private void publish(MqttTopic mqttTopic, MqttMessage message) throws Exception {
if (ObjectUtil.isNotNull(mqttTopic)) {
MqttDeliveryToken token = mqttTopic.publish(message);
token.waitForCompletion();
if (!token.isComplete()) {
log.error("推送消息--失败--msg:{}", JSON.toJSONString(message));
}
} else {
log.error("推送消息--失败--msg:{}", JSON.toJSONString(message));
}
}
}
四、发布消息的回调类
1.发布消息的回调类Java代码
/**
* 发布消息的回调类
* <p>
* 必须实现MqttCallback的接口并实现对应的相关接口方法CallBack 类将实现 MqttCallBack。
* 每个客户机标识都需要一个回调实例。在此示例中,构造函数传递客户机标识以另存为实例数据。
* 在回调中,将它用来标识已经启动了该回调的哪个实例。
* 必须在回调类中实现三个方法:
* public void messageArrived(MqttTopic topic, MqttMessage message)接收已经预订的发布。
* public void connectionLost(Throwable cause)在断开连接时调用。
* public void deliveryComplete(MqttDeliveryToken token))
* 接收到已经发布的 QoS 1 或 QoS 2 消息的传递令牌时调用。
* 由 MqttClient.connect 激活此回调。
* </p>
*/
@Slf4j
public class PushCallback implements MqttCallback {
@Override
public void connectionLost(Throwable cause) {
//连接丢失后,一般在这里面进行重连
log.info("PushCallback--连接断开" + JSON.toJSONString(cause));
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
if (!token.isComplete()) {
log.info("PushCallback--deliveryComplete--异常:" + JSON.toJSONString(token));
}
}
@Override
public void messageArrived(String theme, MqttMessage message) {
try {
log.info("【订阅回调】\ttheme:{}\tqos:{}\npayload:{}", theme, message.getQos(), new String(message.getPayload()));
} catch (Exception e) {
log.error("【订阅回调】--异常\ttheme:{}\nmessage:{}", theme, JSON.toJSONString(message));
}
}
}
五、测试消息发布和消息接收
1.消息发布和消息接收Java代码
@RestController
@RequestMapping("/test")
public class Test {
@Autowired
private MqttUtils mqttUtils;
/**
* 推送消息
*
* @param theme 主题
* @param msg 发送消息
* @return Object <p></p>
* @author SongWei
* @date 2021/5/6 15:08
* @since 1.0.0
*/
@GetMapping("/pushMsg")
public Object pushMsg(@RequestParam(value = "theme", required = false) String theme, @RequestParam(value = "msg") String msg) {
return ResultUtil.isOk(mqttUtils.pushMsg(String.valueOf(System.currentTimeMillis()), theme, msg));
}
/**
* 订阅主题
*
* @param theme 主题
* @return Object <p></p>
* @author SongWei
* @date 2021/5/6 15:08
* @since 1.0.0
*/
@GetMapping("/subscribe")
public Object subscribe(@RequestParam(value = "theme", required = false) String theme) {
return ResultUtil.isOk(mqttUtils.subscribe(theme));
}
}
总结
以上是MQTT消息发布和接收的核心代码,还有一步最关键的是部署MQTT服务器