若依前后端分离版集成MQTT

若依前后端分离版集成MQTT

MQTT是一种轻量级的消息传输协议(Message Queuing Telemetry Transport),旨在实现设备之间的低带宽和高延迟的通信。它是基于发布/订阅模式(Publish/Subscribe)的消息协议,最初由IBM开发,现在成为了一种开放的标准,被广泛应用于物联网(IoT)领域。

MQTT特点包括:

  1. 轻量级:MQTT协议设计简单,消息头部轻量,适用于受限环境的设备,如传感器、嵌入式设备等。
  2. 简单易用:MQTT采用发布/订阅模式,消息的发送者(发布者)和接收者(订阅者)之间解耦,通信过程简单易理解。
  3. 低带宽、高延迟:MQTT协议设计考虑了网络带宽受限和延迟较高的情况,能够在不理想的网络环境下保持稳定的消息传输。
  4. 可靠性:MQTT支持消息的持久化和确认机制,确保消息的可靠传输,同时提供了QoSQuality of Service)等级,可以根据实际需求进行灵活配置。
  5. 灵活性:MQTT支持多种消息格式和负载类型,可以传输文本、二进制数据等多种类型的消息,同时支持SSL/TLS加密,保障通信安全。
  6. 适用于多种场景:由于其轻量级和灵活性,MQTT被广泛应用于物联网、传感器网络、远程监控、消息通知等场景,成为连接设备的重要通信协议之一。

若依前后端分离版集成MQTT步骤如下:

1、下载MQTTX测试工具,进行安装

官网地址:https://www.emqx.com/zh/try?product=emqx-ecp

在这里插入图片描述

2、打开MQTTX,新建连接,输入名称,点击连接

在这里插入图片描述

3、在ruoyi-common模块下的pom.xml加入依赖

<!--mqtt依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-stream</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-mqtt</artifactId>
</dependency>

4、在application.yml添加相关配置,加在Spring配置下,application.ymlruoyi-admin模块的resource目录下

在这里插入图片描述

  mqtt:
    username: admin # 用户名
    password: admin # 密码
    hostUrl: tcp://broker.emqx.io:1883 # tcp://ip:端口
    clientId: clientId # 客户端id
    defaultTopic: topic1 # 订阅主题
    timeout: 100 # 超时时间 (单位:秒)
    keepalive: 60 # 心跳 (单位:秒)
    enabled: true # 是否使用mqtt功能

5、在ruoyi-common\src\main\java\com\ruoyi\common\config目录下新建MqttConfig文件

package com.ruoyi.common.config;

import com.ruoyi.common.client.MqttPushClient;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

/**
 * @author 14820
 */
@Component
@ConfigurationProperties("spring.mqtt")
public class MqttConfig {

    @Autowired
    private MqttPushClient mqttPushClient;

    /**
     * 用户名
     */
    private String username;
    /**
     * 密码
     */
    private String password;
    /**
     * 连接地址
     */
    private String hostUrl;
    /**
     * 客户Id
     */
    private String clientId;
    /**
     * 默认连接话题
     */
    private String defaultTopic;
    /**
     * 超时时间
     */
    private int timeout;
    /**
     * 保持连接数
     */
    private int keepalive;
    /**
     * mqtt功能使能
     */
    private boolean enabled;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getHostUrl() {
        return hostUrl;
    }

    public void setHostUrl(String hostUrl) {
        this.hostUrl = hostUrl;
    }

    public String getClientId() {
        return clientId;
    }

    public void setClientId(String clientId) {
        this.clientId = clientId;
    }

    public String getDefaultTopic() {
        return defaultTopic;
    }

    public void setDefaultTopic(String defaultTopic) {
        this.defaultTopic = defaultTopic;
    }

    public int getTimeout() {
        return timeout;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public int getKeepalive() {
        return keepalive;
    }

    public void setKeepalive(int keepalive) {
        this.keepalive = keepalive;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    @Bean
    public MqttPushClient getMqttPushClient() {
        if (enabled == true) {
            String mqtt_topic[] = StringUtils.split(defaultTopic, ",");
            mqttPushClient.connect(hostUrl, clientId, username, password, timeout, keepalive);//连接
            for (int i = 0; i < mqtt_topic.length; i++) {
                mqttPushClient.subscribe(mqtt_topic[i], 0);//订阅主题
            }
        }
        return mqttPushClient;
    }
}

6、在ruoyi-common\src\main\java\com\ruoyi\common目录下新建client目录,在这个目录中新建

MqttPushClient.javaPushCallback.java文件

MqttPushClient.java

package com.ruoyi.common.client;

import com.ruoyi.common.core.domain.AjaxResult;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import static com.ruoyi.common.core.domain.AjaxResult.error;
import static com.ruoyi.common.core.domain.AjaxResult.success;

/**
 * @author 14820
 */
@Component
public class MqttPushClient {
    private static final Logger logger = LoggerFactory.getLogger(MqttPushClient.class);

    @Autowired
    private PushCallback pushCallback;

    private static MqttClient client;

    private static MqttClient getClient() {
        return client;
    }

    private static void setClient(MqttClient client) {
        MqttPushClient.client = client;
    }

    /**
     * Connect to MQTT broker.
     *
     * @param host      MQTT broker host address.
     * @param clientID  Client ID.
     * @param username  Username for authentication.
     * @param password  Password for authentication.
     * @param timeout   Connection timeout.
     * @param keepalive Keep alive interval.
     */
    public void connect(String host, String clientID, String username, String password, int timeout, int keepalive) {
        try {
            client = new MqttClient(host, clientID, new MemoryPersistence());
            MqttConnectOptions options = createConnectOptions(username, password, timeout, keepalive);
            setClient(client);
            client.setCallback(pushCallback);
            client.connect(options);
        } catch (MqttException e) {
            logger.error("Failed to connect to MQTT broker", e);
        }
    }

    private MqttConnectOptions createConnectOptions(String username, String password, int timeout, int keepalive) {
        MqttConnectOptions options = new MqttConnectOptions();
        options.setCleanSession(true);
        options.setUserName(username);
        options.setPassword(password.toCharArray());
        options.setConnectionTimeout(timeout);
        options.setKeepAliveInterval(keepalive);
        return options;
    }

    /**
     * Publish a message to a topic.
     *
     * @param qos         Quality of Service level.
     * @param retained    Whether the message should be retained.
     * @param topic       Topic to publish to.
     * @param pushMessage Message payload.
     * @return AjaxResult indicating success or failure.
     */
    public AjaxResult publish(int qos, boolean retained, String topic, String pushMessage) {
        MqttMessage message = createMqttMessage(qos, retained, pushMessage);
        MqttTopic mqttTopic = getClient().getTopic(topic);
        if (mqttTopic == null) {
            logger.error("Topic does not exist: {}", topic);
            return error();
        }
        try {
            MqttDeliveryToken token = mqttTopic.publish(message);
            token.waitForCompletion();
            return success();
        } catch (MqttException e) {
            logger.error("Failed to publish message", e);
            return error();
        }
    }

    private MqttMessage createMqttMessage(int qos, boolean retained, String pushMessage) {
        MqttMessage message = new MqttMessage(pushMessage.getBytes());
        message.setQos(qos);
        message.setRetained(retained);
        return message;
    }

    /**
     * Subscribe to a topic.
     *
     * @param topic Topic to subscribe to.
     * @param qos   Quality of Service level.
     */
    public void subscribe(String topic, int qos) {
        logger.info("Subscribing to topic: {}", topic);
        try {
            getClient().subscribe(topic, qos);
        } catch (MqttException e) {
            logger.error("Failed to subscribe to topic: {}", topic, e);
        }
    }
}

PushCallback.java

package com.ruoyi.common.client;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.config.MqttConfig;
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.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author 14820
 */
@Component
public class PushCallback implements MqttCallback {
    private static final Logger logger = LoggerFactory.getLogger(PushCallback.class);

    @Autowired
    private MqttConfig mqttConfig;

    private static MqttClient client;

    private String topic;
    private int qos;
    private String message;

    @Override
    public void connectionLost(Throwable throwable) {
        logger.info("连接断开,可以做重连");
        if (client.isConnected() || client == null) {
            mqttConfig.getMqttPushClient();
        }
    }

    @Override
    public void messageArrived(String topic, MqttMessage mqttMessage) {
        logger.info("接收消息主题 : {}", topic);
        logger.info("接收消息Qos : {}", mqttMessage.getQos());
        logger.info("接收消息内容 : {}", new String(mqttMessage.getPayload()));

        this.topic = topic;
        this.qos = mqttMessage.getQos();
        this.message = new String(mqttMessage.getPayload());
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        logger.info("deliveryComplete---------" + iMqttDeliveryToken.isComplete());
    }

    public String receive() {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("topic", topic);
        jsonObject.put("qos", qos);
        jsonObject.put("msg", message);
        return jsonObject.toString();
    }
}

7、运行项目,后端可以接收MQTTX发来的数据
在这里插入图片描述
在这里插入图片描述

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值