Springboot整合mqtt实现消息的订阅

一、MQTT是什么

        MQTT是一个客户端服务端架构的发布/订阅模式的消息传输协议。它的设计思想是轻巧、开放、简单、规范,易于实现。这些特点使得它对很多场景来说都是很好的选择,特别是对于受限的环境如机器与机器的通信(M2M)以及物联网环境(IoT)。

二、MQTT的主要通讯方式

        MQTT的主要通讯方式是发布与订阅,客户端可以作为消息的发布者,也可以作为消息的订阅者。当发布者对某一主题进行消息的发布后,订阅了同一主题的订阅者便可以接收到发布的信息。在 MQTT 中默认是广播的,也就是说订阅了相同 topic 的订阅者都能收到发布者发送的消息。

三、springboot整合Mqtt

本文主要通过Spring Integration来实现mqtt消息通讯。

Spring Integration 是一个基于 Spring 框架的消息传递框架,它提供了一种将不同应用程序之间的消息传递集成到企业应用程序中的方法。Spring Integration 提供了一组可重用的组件,这些组件可以用于构建消息驱动的应用程序。这些组件包括通道、消息处理器、转换器、适配器等。下图便是Spring Integration生产者-消费者模式。

​编辑

​编辑

1、简述Springboot Integration主要组件的功能:

  • Message 包含 Header 和 Payload 两部分。
  • MessageChannel 用于解耦生产者和消费者,实现消息发送。
  • Service Activitor 用来绑定 MessageHandler 和用于消费消息的 MessageChannel。
  • ChannelAdapter 用来连接 MessageChannel 和具体的消息端口,例如通信的 topic。

2、实现mqtt订阅的主要流程

  • @IntegrationComponentScan,开启 Spring Integration 的注解扫描。
  • 注入客户端工厂类 MqttPahoClientFactory,此处可以配置认证参数、超时时间等 broker 连接参数。
  • 通过注入 MessageProducerSupport 的实例 MqttPahoMessageDrivenChannelAdapter,实现订阅 Topic 和绑定消息消费的 MessageChannel。
  • 注入 MessageChannel 实例。
  • 注入 MessageHandler 的实例,并通过 @ServiceActivator 绑定到对应的 MessageChannel。此处可配置消息处理的模式、QoS、默认的 Topic 等。
  • 通过MessageChannel 的实例 DirectChannel 处理消费细节。Channel 消息后会发送给我们自定义的 MqttInboundMessageHandler 实例进行消费。

3、mqtt的代码实现

        1、注入依赖项:

 <!--        添加mqtt依赖-->
        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-core</artifactId>
        </dependency>
        <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>

        <!--Hutool json处理-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.8</version>
        </dependency>

2、编写配置类的代码:(需要自主在yml文件配置相应属性)

package com.xiaoxie.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@Data
@ConfigurationProperties(prefix = "publish.mqtt")
public class MqttProperties {
    private String url;
    private String clientid;
    private String username;
    private String password;
    private boolean cleansession;
    private String receiveTopics;
    private int timeout;
    private int keepalive;
    private int connectionTimeout;
    
}

3、订阅端代码:

package com.xiaoxie.MqttServer;


import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.xiaoxie.pojo.Lock;
import com.xiaoxie.pojo.Student;
import com.xiaoxie.properties.MqttProperties;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.*;

import java.util.Date;
import java.util.UUID;


//Message 包含 Header 和 Payload 两部分。
//        MessageChannel 用于解耦生产者和消费者,实现消息发送。
//        MessageRouter 用来控制消息转发的 Channel。
//        Service Activitor 用来绑定 MessageHandler 和用于消费消息的 MessageChannel。
//        ChannelAdapter 用来连接 MessageChannel 和具体的消息端口,例如通信的 topic。


@Configuration
@IntegrationComponentScan
public class MqttInboundConfiguration {

    @Autowired
    private MqttProperties mqttProperties;


    @Bean
    public MessageChannel mqttInputChannel() {
        return new DirectChannel();
    }

    @Bean
    public MqttPahoClientFactory mqttInClient() {
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        String[] mqttServerUrls = mqttProperties.getUrl().split(",");
        MqttConnectOptions options = new MqttConnectOptions();
        options.setServerURIs(mqttServerUrls);

        options.setUserName(mqttProperties.getUsername());
        options.setPassword(mqttProperties.getPassword().toCharArray());
        options.setKeepAliveInterval(mqttProperties.getKeepalive());

        //接受离线消息
        options.setCleanSession(false);
        factory.setConnectionOptions(options);

        return factory;
    }

    //  配置Client,监听Topic
    //  如果要配置多个client,模仿此方法,多写几个client
    @Bean
    public MessageProducer inbound() {

        String[] inboundTopics = mqttProperties.getReceiveTopics().split(",");
        MqttPahoMessageDrivenChannelAdapter adapter =
//                new MqttPahoMessageDrivenChannelAdapter(mqttProperties.getClientid() + "_inbound", mqttInClient(), mqttProperties.getReceiveTopics());
                new MqttPahoMessageDrivenChannelAdapter(mqttProperties.getClientid() + "_inbound", mqttInClient(), inboundTopics);
        adapter.setCompletionTimeout(1000 * 5);
        adapter.setQos(0);
        adapter.setOutputChannel(mqttInputChannel());
        return adapter;
    }

    // 通过通道获取数据,即处理 MQTT 发送过来的消息,可以通过 MQTTX 工具发送数据测试
    @Bean
    //ServiceActivator注解表明当前方法用于处理MQTT消息,mqttInputChannel参数指定了用于接收消息信息的渠道
    @ServiceActivator(inputChannel = "mqttInputChannel")  // 异步处理
    public MessageHandler handler() {
        return new MessageHandler() {
            @Override
            public void handleMessage(Message<?> message) throws MessagingException {
                Object payload = message.getPayload();
                MessageHeaders messageHeaders = message.getHeaders();
                String recvTopic = (String) messageHeaders.get(MqttHeaders.RECEIVED_TOPIC);
                //TODO 调用方法,对接收到的数据进行处理
                updateOrStoreSensorData(recvTopic, payload);
            }
        };
    }

    private void updateOrStoreSensorData(String recvTopic, Object payload) {
        if (recvTopic == "RFID"){
            Student cmds = JSONUtil.toBean((String) payload, Student.class);
            System.out.println(cmds.toString());
        } else if (recvTopic == "lock") {
            Lock lock = JSONUtil.toBean((String) payload, Lock.class);
            System.out.println(lock.toString());
        }
    }


}

@ServiceActivator注解就是一个消息端点。消息端点的主要作用是以非侵入性方式将应用程序代码连接到消息传递框架。换句话说,理想情况下,应用程序代码应该不知道消息对象或消息管道。这类似于 MVC 范式中controller 的作用。正如controller 处理 HTTP 请求一样,消息端点处理消息。以及controller 映射到 URL 模式一样,消息端点映射到消息通道。这两种情况的目标是相同的。ServiceActivator是用于将服务实例连接到消息传递系统的通用端点。必须配置输入消息通道,如果要调用的服务方法能够返回值,还可以提供输出消息通道。具体流程如下:

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
非常好的问题!我可以为您提供以下指南来进行springbootmqtt整合开发: 1.首先,在您的SpringBoot应用程序中添加mqtt依赖项。您可以在Maven中添加以下依赖项: ```xml <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-mqtt</artifactId> <version>4.3.18.RELEASE</version> </dependency> ``` 2.其次,您需要配置mqtt连接信息和订阅信息。您可以在application.yaml文件中添加以下配置: ```yaml spring: mqtt: #mqtt发送者配置 producer: host: tcp://localhost:1883 username: admin password: admin topic: test/topic #mqtt消费者配置 consumer: topic: test/+ ``` 3.现在,您可以编写编写代码来监听MQTT消息并处理它们。下面是一个例子: ```java import org.springframework.integration.annotation.MessagingGateway; import org.springframework.integration.mqtt.support.MqttHeaders; import org.springframework.messaging.handler.annotation.Header; @MessagingGateway(defaultRequestChannel = "mqttOutboundChannel") public interface MqttGateway { void sendToMqtt(String data, @Header(MqttHeaders.TOPIC) String topic); } ``` 并在你的bean和配置中加入: ```java @Component public class MyMqttGateway { @Autowired private MqttGateway mqttGateway; public void sendMessage(String message) { mqttGateway.sendToMqtt(message, "test/topic"); } } ``` 4.最后,您需要为应用程序添加一些集成功能,例如订阅并接收MQTT消息。您可以使用以下代码: ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.integration.annotation.IntegrationComponentScan; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.config.EnableIntegration; import org.springframework.integration.dsl.IntegrationFlow; import org.springframework.integration.dsl.IntegrationFlows; @SpringBootApplication @IntegrationComponentScan @EnableIntegration public class Application { @Bean public DirectChannel mqttInputChannel() { return new DirectChannel(); } @Bean public IntegrationFlow mqttInFlow() { return IntegrationFlows.from( Mqtt.messageDrivenChannelAdapter("tcp://localhost:1883", "test/+#") .id("mqttInboundAdapter")) .transform(p -> new String((byte[]) p)) .handle(System.out::println) .get(); } public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 这些是您可以使用的基本步骤。希望这可以帮助您进行springbootmqtt整合开发。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值