Spring boot 集成MQTT

MQTT属于是物联网的通信协议,在MQTT协议中有两大角色:客户端(发布者/订阅者),服务端(Mqtt broker),EMQ和EMQ X就是MQTT服务端的实现方式

EMQX 官网下载地址 Download EMQX

EMQX是什么

EMQ X 基于 Erlang/OTP 平台开发的 MQTT 消息服务器,  支持百万级别分布式服务器

EMQ X 支持丰富的物联网协议,包括 MQTT、MQTT-SN、CoAP、 LwM2M、LoRaWAN 和 WebSocket等;

企业版单机能支持百万的 MQTT 连接;集群能支持千万级别的 MQTT 连接;

EMQX 支持桥接 : 比如EMQX企业版,可以支持将消息转发到kafka,Rabbitmq

安装

Windows安装

/bin/emqx start

访问地址 http://localhost:18083/#/login?to=/dashboard/overview

默认账户密码   admin   public

其他方式安装请参数官网

Pom.xml

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

yml

可自定义

mqtt:
  host: tcp://192.168.38.99:1883
  clientID: 111111
  username: gandegui
  password: Aa123456
  timeout: 30
  keeplive: 30

MQTT配置类

设置了三个客户端订阅

package com.example.kafkademo.mqtt;

import com.example.kafkademo.mqtt.client.MqttCustomerClient;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

/**
 * @description <MQTT配置类>
 * @author: gdg
 * @Date: 2023/7/21
 */
@Component
@Configuration
@Data
//获取yml文件中的配置
@ConfigurationProperties("mqtt")
public class MqttConfiguration {

    @Autowired
    private MqttCustomerClient mqttCustomerClient;


    private String host;
    private String clientId;
    private String username;
    private String password;
    private String topic;

    private int timeout;
    private int keepAlive;

    @Bean
    public MqttCustomerClient getMqttCustomerClient() {
        //mqtt  client 绑定参数
        mqttCustomerClient.connect(host, clientId, username, password, timeout,keepAlive);
        // 以/#结尾表示订阅所有以test开头的主题
        mqttCustomerClient.subscribe("test/#");
        return mqttCustomerClient;
    }


    @Bean
    public MqttCustomerClient getMqttCustomerClient2() {
        //mqtt  client 绑定参数
        mqttCustomerClient.connect(host, "222222s", username, password, timeout,keepAlive);
        // 以/#结尾表示订阅所有以test开头的主题
        mqttCustomerClient.subscribe("test/#");
        return mqttCustomerClient;
    }

    @Bean
    public MqttCustomerClient getMqttCustomerClient3() {
        //mqtt  client 绑定参数
        mqttCustomerClient.connect(host, "333333s", username, password, timeout,keepAlive);
        // 以/#结尾表示订阅所有以test开头的主题
        mqttCustomerClient.subscribe("test/#");
        return mqttCustomerClient;
    }
}

配置MQTT客户端

package com.example.kafkademo.mqtt.client;

import com.example.kafkademo.mqtt.PushCallback;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @description <mqtt客户端>
 * @author: gdg
 * @Date: 2023/7/21
 */
@Slf4j
@Component
public class MqttCustomerClient {

    @Autowired
    private PushCallback pushCallback;

    private  static MqttClient client;

    public  static MqttClient getClient(){
        return  client;
    }

    public static void setClient(MqttClient client){
        MqttCustomerClient.client=client;
    }


    /**
     * 客户端连接
     *
     * @param host      ip+端口
     * @param clientID  客户端Id 也是客户端唯一标识
     * @param username  用户名
     * @param password  密码
     * @param timeout   超时时间  单位秒
     * @param keeplive  心跳发送时间 单位秒
     *
     *   用于在客户端断开连接时保存客户端的状态信息
     *   MemoryPersistence表示使用内存来保存状态信息,也可以使用其他实现来将状态信息保存在文件或数据库中。
     */
    public void  connect(String host,String clientID,String username,String password,int timeout,int keeplive){
        try {
            MqttClient client = new MqttClient(host,clientID,new MemoryPersistence());
            //用于设置MQTT服务器连接参数
            MqttConnectOptions options = new MqttConnectOptions();

            //设置是否启用“清理会话”选项。如果设置为true,则客户端在断开连接时会删除会话信息,包括订阅的主题和QoS等级。
            // 如果设置为false,则客户端会保留会话信息,可以在重新连接时继续之前的订阅
            options.setCleanSession(true);

            // 设置连接使用的用户名。有些MQTT代理服务器需要用户名和密码进行身份验证。
            options.setUserName(username);
            options.setPassword(password.toCharArray());

            //设置连接超时时间
            options.setConnectionTimeout(timeout);

            //设置心跳包的发送间隔,单位是秒。客户端会定期发送心跳包给MQTT代理服务器,用于保持连接的活跃状态
            options.setKeepAliveInterval(keeplive);

            MqttCustomerClient.setClient(client);

            client.setCallback(pushCallback);
            client.connect(options);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发布
     *
     * @param qos         连接方式
     * @param retained    是否保留
     * @param topic       主题
     * @param pushMessage 消息体
     */
    public void pushlish(int qos,boolean retained,String topic,String pushMessage) {
        //设置要发送的消息的相关属性
        MqttMessage message=new MqttMessage();
        //消息可靠性 :
        // QoS为0时,消息不进行确认;
        // QoS为1时,消息至少传递一次,但可能重复;
        // QoS为2时,消息恰好传递一次,且不重复。
        message.setQos(qos);

        //设置消息是否为保留消息   true   false
        //当一个新的订阅者订阅某个主题时
        //如果该主题有保留消息,则会立即将保留消息发送给新的订阅者
        message.setRetained(retained);

        //发送消息体
        message.setPayload(pushMessage.getBytes());

        //从客户端中获取一个发布消息的MQTT主题(MqttTopic)对象
        MqttTopic mqttTopic= MqttCustomerClient.getClient().getTopic(topic);
        if(null== mqttTopic){
            log.error("topic not exist");
        }

        try {
//            当你通过MQTT客户端发布一条消息到指定的主题时,该操作是异步的,
//            发布操作会立即返回,但实际的消息投递可能需要一定的时间
//            MqttDeliveryToken的作用就是监听消息的投递状态

//            token.waitForCompletion()   该方法会阻塞直到消息被成功发送或投递失败
            //token.isComplete()  判断消息是否已经投递完成
            //也可以实现 IMqttActionListener 接口通过回调函数,处理消息投递成功和失败的逻辑

            MqttDeliveryToken token = mqttTopic.publish(message);
            token.waitForCompletion();
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发布,默认qos为0,消息不进行确认
     * @param topic
     * @param pushMessage
     */
    public void pushlish(String topic,String pushMessage){
        pushlish(0,false,topic,pushMessage);
    }


    /**
     * 订阅某个主题,qos默认为0
     * @param topic
     */
    public void subscribe(String topic){
        log.error("开始订阅主题" + topic);
        subscribe(topic,0);
    }

    public void subscribe(String topic,int qos){
        try {
            MqttCustomerClient.getClient().subscribe(topic,qos);
        }catch (MqttException e){
            e.printStackTrace();
        }
    }

}

消息监听与回调通知

package com.example.kafkademo.mqtt;

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.springframework.stereotype.Component;

/**
 * @description <功能描述>
 * @author: gdg
 * @Date: 2023/7/21
 * MqttCallback   用于接收MQTT客户端与MQTT服务器之间的消息交互的回调接口
 *
 * 当MQTT客户端订阅了一个主题,或者发布消息到某个主题时
 * 服务器会通过MqttCallback接口中定义的一些方法来通知客户端相关的状态和数据。
 */
@Component
public class PushCallback implements MqttCallback {
    private static MqttClient client;
    /**
     * 当MQTT客户端与MQTT服务器的连接丢失时,connectionLost方法会被调用
     * */
    @Override
    public void connectionLost(Throwable throwable) {
        if (client == null || !client.isConnected()) {
            System.out.println("连接断开,正在重连....");
        }
    }


    /**
     * 当客户端接收到消息时,这个方法会被调用,可以在这个方法中处理接收到的消息
     * */
    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {
        System.out.println("客户端接收消息主题 : " + topic);
        System.out.println("客户端接收消息Qos : " + message.getQos());
        System.out.println("客户端接收消息内容 : " + new String(message.getPayload()));

    }


    /**
     * 当MQTT客户端成功发送一条消息到MQTT服务器,并且服务器确认收到消息后,deliveryComplete方法会被调用
     * 通常用于处理消息的发送缺
     * 你可以执行一些操作来确认消息发送成功,例如更新消息的状态、记录日志等
     * */
    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        System.out.println("deliveryComplete---------" + token.isComplete());
    }
}

 测试方法

    @Autowired
    private MqttCustomerClient mqttCustomerClient;

    @Test
    void pushlish() throws InterruptedException {
            for (int i = 0; i < 5000; i++) {
                mqttCustomerClient.pushlish("test/device1", "发送消息 -----------"+Thread.currentThread().getName());
                Thread.sleep(1000);

            }

    }

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值