MQTT教程详解-04.SpringBoot集成MQTT(告别手动控制)

基三个核心依赖,Spring Boot 整合 MQTT 完整实战代码。

1. 引入 Maven 依赖 (pom.xml)

在你的 pom.xml 文件中加入以下三个核心依赖(包含 Spring Boot 集成基础、MQTT 适配器和 Stream 流处理):

XML 复制代码
<dependencies>
    <!-- Spring Boot 集成基础(提供自动配置和核心架构) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-integration</artifactId>
    </dependency>
    <!-- MQTT 协议适配器 -->
    <dependency>
        <groupId>org.springframework.integration</groupId>
        <artifactId>spring-integration-mqtt</artifactId>
    </dependency>
    <!-- Stream 流处理支持 -->
    <dependency>
        <groupId>org.springframework.integration</groupId>
        <artifactId>spring-integration-stream</artifactId>
    </dependency>
</dependencies>

这三个依赖都是 Spring 生态中用于处理消息和集成的核心组件。

场景设想 :你的应用需要接收来自物联网设备的 MQTT 消息(spring-integration-mqtt),在应用内部进行流式处理(spring-integration-stream),而整个框架的底层支撑和自动配置则由 spring-boot-starter-integration 提供。

1.1. 基础依赖:spring-boot-starter-integration 🛠️

这是 Spring Boot 的启动器(Starter),它的作用是"一键引入" Spring Integration 的核心能力,并开启自动配置1。你不需要手动去配置繁琐的 XML 或基础 Bean。

核心作用:

它提供了 Spring Integration 的基础架构,包括消息通道(MessageChannel)消息(Message) 以及基于注解(如 @ServiceActivator)的编程模型4。

1.2. 外部通信:spring-integration-mqtt 📡

这个模块提供了与 MQTT 代理(Broker)进行双向通信的适配器。在 Spring Integration 中,通常包含"入站适配器"(接收消息)和"出站处理器"(发送消息)。

1.3. 内部流处理:spring-integration-stream 🌊

spring-integration-stream 主要用于处理基于流(Stream)的数据,比如标准输入输出(System.in/out)、文件流或网络流3。同时,在现代 Spring Integration 中,我们常用它的 Java DSL(流式 API) 来编排消息的处理流程(过滤、转换、聚合等)

总结三者关系
组件 角色定位 通俗比喻
spring-boot-starter-integration 地基与总管 像是房子的地基和水电总闸,提供了运行环境和基础能力。
spring-integration-mqtt 对外接口 像是大门和邮筒,专门负责和外部特定的系统(MQTT 服务器)收发信件。
spring-integration-stream 内部流水线 像是屋内的传送带和处理工人,负责把大门收进来的信件进行筛选、加工和流转。

通过这三者的结合,可以轻松构建出一个既能与物联网设备通信,又能在内部高效处理业务逻辑的消息驱动应用。

org.eclipse.paho.client.mqttv3 是最核心的底层零件,spring-integration-mqtt 是对它的专属包装,spring-integration-stream 是处理管道流水线的工具,而 spring-boot-starter-integration 则是包含这一切并帮你一键启动的完整大礼包。

下面是它们各自的详细区别与定位:

1. org.eclipse.paho.client.mqttv3(底层核心驱动)

  • 定位 :这是 Eclipse 基金会提供的 MQTT 协议底层客户端库(Java 实现)3。
  • 作用:它是最基础的工具,直接负责建立 TCP 连接、处理 MQTT 协议的握手、发布(Publish)、订阅(Subscribe)等底层网络通信工作2。
  • 特点:非常轻量,但如果你直接使用它,需要自己手写大量的代码来处理断线重连、异常捕获、线程调度等复杂逻辑20。
  • 注意 :从 Spring Integration 6.5 版本开始,这个依赖变成了 optional(可选),这意味着如果你使用新版框架,必须在项目中显式引入它,否则运行时会报错1。

2. spring-integration-mqtt(MQTT 专属适配器)

  • 定位 :这是 Spring Integration 框架中专门用于对接 MQTT 协议的模块/适配器3。
  • 作用 :它在 paho 的基础上进行了二次封装。它把底层的 MQTT 连接包装成了 Spring 消息流中的"入站适配器"(接收消息)和"出站适配器"(发送消息)5。
  • 特点 :帮你解决了繁琐的重连机制、Spring 容器生命周期管理等难题19。你只需要配置一下 Bean,就能让它融入 Spring 的消息处理管道中5。它底层默认调用的就是 paho

3. spring-integration-stream(流式处理组件)

  • 定位 :这是 Spring Integration 框架中用于处理 IO 流(Stream)的通用组件3。
  • 作用:它主要用于在消息流中对数据进行转换、读取或写入。比如从控制台输入(stdin)读取数据,或者将消息写入到文件输出流(stdout)中6。
  • 区别 :它和 MQTT 没有直接关系。它处理的是"数据流"的转换,而 spring-integration-mqtt 处理的是"MQTT 协议"的对接。两者经常在项目中一起出现,是因为它们都属于 Spring Integration 大家族3。

4. spring-boot-starter-integration(Spring Boot 启动器)

  • 定位 :这是 Spring Boot 提供的自动化配置启动器16。
  • 作用 :它是一个"聚合包"。只要在你的 Maven/Gradle 中引入它,Spring Boot 就会自动帮你配置好 Spring Integration 的基础环境(比如自动开启 @EnableIntegration、配置默认的线程池调度器等)4。
  • 特点 :它本身不包含 MQTT 的功能,但它为使用 spring-integration-mqtt 等模块提供了最便捷的土壤10。

📌 总结与依赖关系

它们在实际项目中的依赖和使用关系如下:

  1. 最底层org.eclipse.paho.client.mqttv3(干脏活累活的)
  2. 中间层spring-integration-mqtt(依赖 paho,把它包装成 Spring 能用的组件)
  3. 基础环境spring-boot-starter-integration(为整个 Spring Integration 体系提供自动配置)
  4. 旁支工具spring-integration-stream(如果需要做流式数据处理时才会用到,与 MQTT 平行)

💡 避坑建议:

如果你在 Spring Boot 3.x 项目中集成 MQTT,标准的"全家桶"引入方式通常是:

  • 引入 spring-boot-starter-integration(搭建基础环境)
  • 引入 spring-integration-mqtt(获取 MQTT 适配能力)
  • 手动显式引入 org.eclipse.paho.client.mqttv3(防止新版框架将其设为可选依赖后导致运行时缺失)1

2. 配置文件 (application.yml)

src/main/resources/application.yml 中配置 MQTT 服务器的连接信息:

XML 复制代码
spring:
  mqtt:
    broker-url: tcp://127.0.0.1:1883  # MQTT 服务器地址
    username: admin                   # 账号
    password: public                  # 密码
    client-id: spring-boot-mqtt-${random.value} # 客户端ID(保证唯一)
    default-topic: test/topic/#       # 默认订阅的主题(#代表多级通配符)
    completion-timeout: 3000          # 连接超时时间(毫秒)

3. 核心配置类 (MqttConfig.java)

这个类负责将 MQTT 的入站(接收)、出站(发送)与 Spring Integration 的消息通道(Channel)绑定起来:

java 复制代码
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.outbound.MqttPahoMessageHandler;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;

@Configuration
public class MqttConfig {

    @Value("${spring.mqtt.broker-url}")
    private String brokerUrl;
    @Value("${spring.mqtt.username}")
    private String username;
    @Value("${spring.mqtt.password}")
    private String password;
    @Value("${spring.mqtt.client-id}")
    private String clientId;
    @Value("${spring.mqtt.default-topic}")
    private String defaultTopic;
    @Value("${spring.mqtt.completion-timeout}")
    private int completionTimeout;

    // 1. 配置 MQTT 连接选项
    @Bean
    public MqttPahoClientFactory mqttClientFactory() {
        DefaultMqttPahoClientFactory factory 
                            = new DefaultMqttPahoClientFactory();

        MqttConnectOptions options = new MqttConnectOptions();
        options.setServerURIs(new String[]{brokerUrl});
        options.setUserName(username);
        options.setPassword(password.toCharArray());
        // 断线自动重连
        options.setKeepAliveInterval(60);
        options.setAutomaticReconnect(true); 
        options.setCleanSession(true);
        factory.setConnectionOptions(options);
        return factory;
    }

    // 2. 定义入站和出站的消息通道(内部管道)
    @Bean
    public MessageChannel mqttInputChannel() {
        return new DirectChannel();
    }

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

    // 3. 入站适配器:监听 MQTT 主题,将消息推送到 mqttInputChannel
    @Bean
    public MessageProducer inbound() {
        MqttPahoMessageDrivenChannelAdapter adapter
               = new MqttPahoMessageDrivenChannelAdapter(
                clientId + "-inbound", mqttClientFactory(), defaultTopic);

        adapter.setCompletionTimeout(completionTimeout);
        adapter.setConverter(new DefaultPahoMessageConverter());
        adapter.setQos(1);
        adapter.setOutputChannel(mqttInputChannel());
        return adapter;
    }

    // 4. 出站处理器:从 mqttOutboundChannel 获取消息,发布到 MQTT
    @Bean
    @ServiceActivator(inputChannel = "mqttOutboundChannel")
    public MessageHandler outbound() {

        MqttPahoMessageHandler messageHandler
         = new MqttPahoMessageHandler(
                clientId + "-outbound", mqttClientFactory());

        messageHandler.setAsync(true);
        messageHandler.setDefaultQos(1);
        return messageHandler;
    }
}
  • 入站(Inbound)MqttPahoMessageDrivenChannelAdapter 负责把外部的 MQTT 消息"拉"进来,转成 Spring 的 Message 对象放到通道里2。
  • 出站(Outbound)MqttPahoMessageHandler 负责把通道里的消息"推"出去,发给 MQTT 服务器2。

4. 消息发送网关 (MqttGateway.java)

使用 @MessagingGateway 注解,让 Spring 自动为我们生成发送消息的实现类:

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(@Header(MqttHeaders.TOPIC) String topic, String payload);
}

5. 消息接收与流处理 (MqttMessageHandler.java)

这里结合 spring-integration-stream 的流式思想,使用 Java DSL 对接收到的消息进行过滤、转换和处理:

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.messaging.MessageChannel;

@Configuration
public class MqttMessageHandler {

    // 假设这里接收来自 MqttConfig 中 mqttInputChannel 的消息
    // 实际开发中也可以直接在 MqttConfig 的 inbound() 方法后直接接 .handle()
    @Bean
    public IntegrationFlow mqttDataFlow(DirectChannel mqttInputChannel) {
        return IntegrationFlow.from(mqttInputChannel)
                // 1. 过滤:只处理非空消息
                .filter(payload -> payload != null)
                // 2. 转换:将消息内容转为大写(演示流处理能力)
                .transform(String.class, String::toUpperCase)
                // 3. 处理:打印接收到的消息
                .handle(message -> {
                    String topic = message.getHeaders()
                                    .get("mqtt_receivedTopic", String.class);
                    String payload = (String) message.getPayload();
                    System.out.println("【收到消息】主题: " + topic
                                             + ",内容: " + payload);
                })
                .get();
    }
}

代码详解(结合 MQTT 场景):

假设我们要处理从 MQTT 收到的消息:过滤掉无效数据,将有效数据转为大写,最后打印出来(模拟写入流)。

  • IntegrationFlows :这是 Spring Integration 提供的流式 API,非常符合 spring-integration-stream 的设计理念。
  • 处理链.filter() -> .transform() -> .handle() 构成了一个清晰的消息处理流水线7。

6. 业务测试 (MqttController.java)

最后,写一个简单的 Controller 来测试消息的发送:

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MqttController {

    @Autowired
    private MqttGateway mqttGateway;

    @GetMapping("/send")
    public String sendMqtt(@RequestParam String topic,
                           @RequestParam String message) {

        mqttGateway.sendToMqtt(topic, message);
        return "消息发送成功!主题:" + topic + ",内容:" + message;
    }
}

运行测试:

  1. 启动 Spring Boot 应用。
  2. 访问 http://localhost:8080/send?topic=test/topic&message=hello_mqtt
  3. 你的控制台会打印出经过流处理(转为大写)后的消息内容,同时你的 MQTT 客户端(如 MQTTX)订阅 test/topic 也能收到原始消息。
相关推荐
语戚1 小时前
力扣 3161. 块放置查询:线段树解法(Java 实现)
java·算法·leetcode·面试·线段树·力扣·
我命由我123452 小时前
Android 开发问题:MlKitException: An internal error occurred during initialization.
android·java·java-ee·android jetpack·android-studio·androidx·android runtime
888CC++2 小时前
java 并发编程
java·开发语言·python
无风听海2 小时前
JSON Web Token(JWT)完全指南
java·前端·json
JAVA社区3 小时前
Java高级全套教程(十一)—— Kubernetes 超详细企业级实战详解
java·运维·微服务·容器·面试·kubernetes
在繁华处4 小时前
Java从零到熟练(九):并发编程基础
java·开发语言
木头程序员4 小时前
SSM框架学习笔记
java·开发语言·mysql·spring·maven
李白你好4 小时前
页面资产梳理 · 技术指纹识别 · Spring 端点探测
java·后端·spring
一起逃去看海吧4 小时前
dify-03
java·linux·开发语言