SpringBoot整合RabbitMQ mqtt协议实现发布/订阅

       

        MQTT(Message Queuing Telemetry Transport):MQTT是一种轻量级的发布/订阅消息传递协议,设计初衷是用于低带宽、高延迟或不稳定的网络环境中。它适用于远程位置的设备,通常在物联网环境中使用。RabbitMQ通过插件的方式支持MQTT协议。

1、RabbitMQ 配置MQTT 端口映射(mq安装目录sbin文件夹,win下需管理员身份运行cmd)

#开启WEB管理
rabbitmq-plugins enable rabbitmq_management
#开启MQTT插件
rabbitmq-plugins enable rabbitmq_mqtt

执行成功后会开启以下两个端口:(rabbitmq web管理页面验证 例:localhost:15672)

rabbitmq_mqtt:默认端口 1883 提供与后端服务交互使用

rabbitmq_web_mqtt:默认端口15675 websocket协议 提供与前端交互使用

2、MQTT 数据可视化工具——模拟消息发布订阅

3、MQTT整合Spring项目

        (一)pom.xml 引入依赖

<!-- 引入 mqtt 相关依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-integration</artifactId>
    <version>2.3.12.RELEASE</version>
</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>

        (二)application.yml 添加配置信息

# 数据源配置
spring:
  application:
    name: ****示例 #服务名称
  mqtt:
    url: tcp://你的IP:1883 # MQTT 客户端连接地址 1883固定 
    username: admin #rabbitMq 账号
    password: ******** #rabbitMq 密码

        (三)mqtt 配置类

import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * @program: 
 * @ClassName MqttConfig
 * @description: mqtt 配置
 * @author: Yang
 * @create: 2024-04-02 16:17
 * @Version 1.0
 **/
@Configuration
public class MqttConfig {

    @Value("${spring.mqtt.username}")
    private String username;

    @Value("${spring.mqtt.password}")
    private String password;

    @Value("${spring.mqtt.url}")
    private String hostUrl;

    @Value("${spring.application.name}")
    private String applicationName;

    /**
     * 客户端对象
     */
    private MqttClient client;

    /**
     * 在bean初始化后连接到服务器
     */
    @PostConstruct
    public void init() {
        this.connect();
    }

    /**
     * 断开连接
     */
    @PreDestroy
    public void disConnect() {
        try {
            client.disconnect();
            client.close();
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    /**
     * 客户端连接服务端
     */
    public void connect() {
        try {
            // 创建MQTT客户端对象
            client = new MqttClient(hostUrl, applicationName, new MemoryPersistence());
            // 连接设置
            MqttConnectOptions options = new MqttConnectOptions();
            // 是否清空session,设置false表示服务器会保留客户端的连接记录(订阅主题,qos),客户端重连之后能获取到服务器在客户端断开连接期间推送的消息
            // 设置为true表示每次连接服务器都是以新的身份
            options.setCleanSession(true);
            // 设置连接用户名
            options.setUserName(username);
            // 设置连接密码
            options.setPassword(password.toCharArray());
            // 设置超时时间,单位为秒
            options.setConnectionTimeout(100);
            // 设置心跳时间 单位为秒,表示服务器每隔 1.5*20秒的时间向客户端发送心跳判断客户端是否在线
            options.setKeepAliveInterval(20);
            // 设置遗嘱消息的话题,若客户端和服务器之间的连接意外断开,服务器将发布客户端的遗嘱信息
            options.setWill("willTopic", (applicationName + "与服务器断开连接").getBytes(), 0, false);
            // 设置回调
            client.setCallback(new MqttCallBack());
            // 连接
            client.connect(options);
            // 订阅主题 (接受此主题的消息)
//            this.subscribe("warn_topic", 2);
        } catch (MqttException e) {
            e.printStackTrace();
        }

    }

    /**
     * 发布消息
     *
     * @param topic
     * @param message
     */
    public boolean publish(String topic, String message) {
        MqttMessage mqttMessage = new MqttMessage();
        // 0:最多交付一次,可能丢失消息
        // 1:至少交付一次,可能消息重复
        // 2:只交付一次,既不丢失也不重复
        mqttMessage.setQos(2);
        // 是否保留最后一条消息
        mqttMessage.setRetained(false);
        // 消息内容
        mqttMessage.setPayload(message.getBytes());
        // 主题的目的地,用于发布/订阅信息
        MqttTopic mqttTopic = client.getTopic(topic);
        // 提供一种机制来跟踪消息的传递进度
        // 用于在以非阻塞方式(在后台运行)执行发布是跟踪消息的传递进度
        MqttDeliveryToken token;
        try {
            // 将指定消息发布到主题,但不等待消息传递完成,返回的token可用于跟踪消息的传递状态
            // 一旦此方法干净地返回,消息就已被客户端接受发布,当连接可用,将在后台完成消息传递。
            token = mqttTopic.publish(mqttMessage);
            token.waitForCompletion();
            return true;
        } catch (MqttException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 订阅主题
     */
    public void subscribe(String topic, int qos) {
        try {
            client.setCallback(new MqttCallBack());
            client.subscribe(topic, qos);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
}

        (四)mqtt 回调方法类

import lombok.extern.slf4j.Slf4j;
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;

/**
 * @program: 
 * @ClassName MqttCallBack
 * @description: mqtt发送回调
 * @author: Yang
 * @create: 2024-04-02 16:18
 * @Version 1.0
 **/
@Slf4j
@Configuration
public class MqttCallBack implements MqttCallback {
    /**
     * 与服务器断开的回调
     */
    @Override
    public void connectionLost(Throwable cause) {
        log.error("与服务器断开连接");
    }

    /**
     * 消息到达的回调
     */
    @Override
    public void messageArrived(String topic, MqttMessage message) {
        log.info("【发送】消息主题:【{}】", topic);
        log.info("【发送】消息Qos:【{}】", message.getQos());
        log.info("【发送】消息内容:【{}】", new String(message.getPayload()));
        log.info("【发送】消息retained:【{}】", message.isRetained());
    }

    /**
     * 消息发布成功的回调
     */
    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        IMqttAsyncClient client = token.getClient();
        log.info("【发送】【{}】##########发布消息成功!",client.getClientId());
    }
}

        (五)发布消息测试类

import cn.konne.businessscreen.config.MqttConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @program: 
 * @ClassName TestController
 * @description: 测试发布信息
 * @author: Yang
 * @create: 2024-04-02 16:19
 * @Version 1.0
 **/
@RestController
@RequestMapping(value = "/test")
public class MqttSendController {

    @Autowired
    private MqttConfig mqttConfig;

    @GetMapping("/sendMessage")
    public String sendMessage(@RequestParam("topic") String topic,
                              @RequestParam("message") String message) {
        boolean publish = mqttConfig.publish(topic, message); //发布消息
        mqttConfig.subscribe(topic,2); //订阅信息
        if (publish) {
            return "ok";
        }
        return "no";
    }
}

        (六)订阅消息

import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;

import java.util.Random;

/**
 * @program: 
 * @ClassName MyMqttClient
 * @description: 订阅消息
 * @author: Yang
 * @create: 2024-04-02 17:21
 * @Version 1.0
 **/
@Slf4j
public class MqttClient {

    //MQTTurl
    private static String url="tcp://你的IP:1883";
    //MQTTid头
    private static String clientId="mqtt_";
    //创建MQTT对象
    private static MqttCallback cb=new MqttCallback() {
        @Override
        public void connectionLost(Throwable throwable) {
        }

        @Override
        public void messageArrived(String topic, MqttMessage message) throws Exception {
            log.info("【接收】消息主题:【{}】", topic);
            log.info("【接收】消息Qos:【{}】", message.getQos());
            log.info("【接收】消息内容:【{}】", new String(message.getPayload()));
            log.info("【接收】消息retained:【{}】", message.isRetained());
        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        }
    };
    private static org.eclipse.paho.client.mqttv3.MqttClient client;


    public static void main(String[] args) throws MqttException {
        //注意id唯一
        client=new org.eclipse.paho.client.mqttv3.MqttClient(url,clientId+new Random().nextInt(100000));
        MqttConnectOptions options=new MqttConnectOptions();
        options.setUserName("rabbitMq账号");
        options.setPassword("rabbitMq密码".toCharArray());
        client.setCallback(cb);
        client.connect(options);
        log.info("【接收】已开启订阅,等待消息");
        // 订阅主题 (接受此主题的消息) 更改为自己的订阅主题
        client.subscribe("warn_topic",2);
    }
}

        (七)发布消息 验证是否成功

发布日志:

16:41:16.368 [http-nio-8080-exec-2] INFO  o.a.c.c.C.[.[.[/] - [log,173] - Initializing Spring DispatcherServlet 'dispatcherServlet'
16:41:16.086 [MQTT Call: mqtt_demo] INFO  c.k.b.c.MqttCallBack - [deliveryComplete,46] - 【发送】【mqtt_demo】##########发布消息成功!
16:41:16.086 [MQTT Call: mqtt_demo] INFO  c.k.b.c.MqttCallBack - [messageArrived,34] - 【发送】消息主题:【warn_topic】
16:41:16.087 [MQTT Call: mqtt_demo] INFO  c.k.b.c.MqttCallBack - [messageArrived,35] - 【发送】消息Qos:【1】
16:41:16.087 [MQTT Call: mqtt_demo] INFO  c.k.b.c.MqttCallBack - [messageArrived,36] - 【发送】消息内容:【这是一条测试数据】
16:41:16.087 [MQTT Call: mqtt_demo] INFO  c.k.b.c.MqttCallBack - [messageArrived,37] - 【发送】消息retained:【false】

订阅日志:

16:41:16.032 [main] INFO  c.k.b.c.MqttClient - [main,52] - 【接收】已开启订阅,等待消息
16:41:16.086 [MQTT Call: mqtt_lx_49539] INFO  c.k.b.c.MqttClient - [messageArrived,31] - 【接收】消息主题:【warn_topic】
16:41:16.107 [MQTT Call: mqtt_lx_49539] INFO  c.k.b.c.MqttClient - [messageArrived,32] - 【接收】消息Qos:【1】
16:41:16.108 [MQTT Call: mqtt_lx_49539] INFO  c.k.b.c.MqttClient - [messageArrived,33] - 【接收】消息内容:【这是一条测试数据】
16:41:16.109 [MQTT Call: mqtt_lx_49539] INFO  c.k.b.c.MqttClient - [messageArrived,34] - 【接收】消息retained:【false】

至此,完成Spring boot 整合 RabbitMQ 实现MQTT数据传输的使用示例。

如果这篇文章对您有帮助,动动发财小手,点个赞支持一下,感谢大家!

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Spring Boot集成RabbitMQMQTT可以使用Spring Boot的AMQP和Paho客户端库。以下是集成步骤: 1. 添加依赖 在pom.xml添加以下依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.eclipse.paho.client.mqttv3</artifactId> <version>1.2.0</version> </dependency> ``` 2. 配置RabbitMQ连接 在application.properties配置RabbitMQ连接信息: ``` spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest ``` 3. 创建RabbitMQ消息接收者 创建一个类来接收RabbitMQ消息。在该类,使用@RabbitListener注解标记方法,指定队列名称和消息处理方法。 ``` @Component public class RabbitMQReceiver { @RabbitListener(queues = "test") public void receive(String message) { // 处理消息 } } ``` 4. 创建MQTT消息接收者 创建一个类来接收MQTT消息。在该类实现MqttCallback接口,重写messageArrived方法来处理接收到的消息。 ``` @Component public class MQTTReceiver implements MqttCallback { @Override public void connectionLost(Throwable throwable) { // 连接丢失 } @Override public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception { // 处理消息 } @Override public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) { // 消息发送完成 } } ``` 5. 创建RabbitMQ消息发送者 创建一个类来发送RabbitMQ消息。在该类,注入AmqpTemplate并调用convertAndSend方法来发送消息到指定队列。 ``` @Component public class RabbitMQSender { @Autowired private AmqpTemplate amqpTemplate; public void send(String message) { amqpTemplate.convertAndSend("test", message); } } ``` 6. 创建MQTT消息发送者 创建一个类来发送MQTT消息。在该类,注入MqttClient并调用connect、publish和disconnect方法来发送消息。 ``` @Component public class MQTTSender { @Autowired private MqttClient mqttClient; @Autowired private MqttConnectOptions mqttConnectOptions; public void send(String topic, String message) throws MqttException { MqttMessage mqttMessage = new MqttMessage(message.getBytes()); mqttClient.connect(mqttConnectOptions); mqttClient.publish(topic, mqttMessage); mqttClient.disconnect(); } } ``` 以上是在Spring Boot集成RabbitMQMQTT实现消息订阅和发送的基本步骤。需要注意的是,AMQP和MQTT是不同的消息协议,需要根据实际情况选择使用哪个协议。另外,需要确保网络通畅,否则可能会出现消息丢失等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值