基三个核心依赖,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。
📌 总结与依赖关系
它们在实际项目中的依赖和使用关系如下:
- 最底层 :
org.eclipse.paho.client.mqttv3(干脏活累活的) - 中间层 :
spring-integration-mqtt(依赖 paho,把它包装成 Spring 能用的组件) - 基础环境 :
spring-boot-starter-integration(为整个 Spring Integration 体系提供自动配置) - 旁支工具 :
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;
}
}
运行测试:
- 启动 Spring Boot 应用。
- 访问
http://localhost:8080/send?topic=test/topic&message=hello_mqtt。 - 你的控制台会打印出经过流处理(转为大写)后的消息内容,同时你的 MQTT 客户端(如 MQTTX)订阅
test/topic也能收到原始消息。