Spring Boot 集成 RabbitMQ MQTT 协议实现消息通信
引言
随着物联网(IoT)技术的快速发展,MQTT(Message Queuing Telemetry Transport)协议因其轻量级、低带宽占用的特点,成为了设备间通信的首选协议。而 RabbitMQ 作为功能强大的消息代理,通过其 MQTT 插件,可以轻松实现 MQTT 协议的支持。本文将详细介绍如何在 Spring Boot 应用中集成 RabbitMQ MQTT 协议,实现消息的发布与订阅。
项目概述
本文所介绍的项目是一个基于 Spring Boot 的应用,演示了 RabbitMQ 与 MQTT 协议的集成。项目主要实现了以下功能:
- MQTT 客户端连接:建立与 RabbitMQ MQTT 服务器的连接
- 消息发布:向 MQTT 主题发布消息
- 消息订阅:订阅 MQTT 主题并处理接收到的消息
- 周期性消息发布:每 5 秒自动发布一次消息,演示持续发布功能
- JSON 消息格式:发送带有时间戳的 JSON 格式消息
前置要求
在开始之前,需要确保以下环境已经准备就绪:
- Java 17 或更高版本
- Maven 3.6+ 或 Gradle 7+
- RabbitMQ Server 3.10+
此外,还需要在 RabbitMQ 服务器中启用 rabbitmq_mqtt 插件:
bash
# Linux/macOS 系统
rabbitmq-plugins enable rabbitmq_mqtt
# Windows 系统 (PowerShell)
rabbitmq-plugins.bat enable rabbitmq_mqtt
项目结构
项目采用标准的 Spring Boot 项目结构,主要包含以下文件:
rabbitmq-mqtt-integration/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ └── rabbitmqmqtt/
│ │ │ ├── RabbitMqMqttIntegrationApplication.java # 应用入口
│ │ │ ├── config/
│ │ │ │ ├── MqttConfig.java # MQTT 客户端配置
│ │ │ │ └── MqttIntegrationConfig.java # MQTT 入站/出站适配器
│ │ │ ├── consumer/
│ │ │ │ └── MqttConsumer.java # MQTT 消息消费者
│ │ │ └── producer/
│ │ │ └── MqttProducer.java # MQTT 消息生产者
│ │ └── resources/
│ │ └── application.yml # 应用配置
├── pom.xml # Maven 依赖
└── README.md # 项目说明
技术实现
1. MQTT 客户端配置
MqttConfig.java 文件负责配置 MQTT 客户端连接选项和客户端工厂:
java
@Configuration
public class MqttConfig {
@Value("${mqtt.broker.url}")
private String brokerUrl;
@Value("${mqtt.broker.username}")
private String username;
@Value("${mqtt.broker.password}")
private String password;
@Value("${mqtt.broker.client-id}")
private String clientId;
@Bean
public MqttConnectOptions mqttConnectOptions() {
MqttConnectOptions options = new MqttConnectOptions();
options.setServerURIs(new String[]{brokerUrl});
options.setUserName(username);
options.setPassword(password.toCharArray());
options.setCleanSession(true);
options.setConnectionTimeout(30);
options.setKeepAliveInterval(60);
return options;
}
@Bean
public MqttPahoClientFactory mqttClientFactory() {
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
factory.setConnectionOptions(mqttConnectOptions());
return factory;
}
}
2. MQTT 集成配置
MqttIntegrationConfig.java 文件配置了 MQTT 入站和出站适配器:
java
@Configuration
@IntegrationComponentScan
public class MqttIntegrationConfig {
@Value("${mqtt.broker.client-id}")
private String clientId;
@Value("${mqtt.topic.subscribe}")
private String subscribeTopic;
@Value("${mqtt.topic.qos}")
private int qos;
private final MqttConsumer mqttConsumer;
public MqttIntegrationConfig(MqttConsumer mqttConsumer) {
this.mqttConsumer = mqttConsumer;
}
@Bean
public MessageChannel mqttInputChannel() {
return new DirectChannel();
}
@Bean
public MessageChannel mqttOutputChannel() {
return new DirectChannel();
}
@Bean
public MqttPahoMessageDrivenChannelAdapter mqttInboundAdapter(MqttPahoClientFactory clientFactory) {
String inboundClientId = clientId + "-inbound";
MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(
inboundClientId, clientFactory, subscribeTopic);
adapter.setCompletionTimeout(5000);
adapter.setConverter(new DefaultPahoMessageConverter());
adapter.setQos(qos);
adapter.setOutputChannel(mqttInputChannel());
return adapter;
}
@Bean
@ServiceActivator(inputChannel = "mqttInputChannel")
public MessageHandler mqttInboundHandler() {
return message -> {
String payload = (String) message.getPayload();
mqttConsumer.handleMessage(payload);
};
}
@Bean
@ServiceActivator(inputChannel = "mqttOutputChannel")
public MqttPahoMessageHandler mqttOutboundAdapter(MqttPahoClientFactory clientFactory) {
String outboundClientId = clientId + "-outbound";
MqttPahoMessageHandler handler = new MqttPahoMessageHandler(outboundClientId, clientFactory);
handler.setAsync(true);
handler.setDefaultTopic("demo/publish");
handler.setDefaultQos(qos);
return handler;
}
@MessagingGateway(defaultRequestChannel = "mqttOutputChannel")
public interface MqttGateway {
void sendToMqtt(String payload);
void sendToMqtt(String topic, String payload);
void sendToMqtt(String topic, int qos, String payload);
}
}
3. 消息消费者
MqttConsumer.java 文件负责处理从 MQTT 主题接收到的消息:
java
@Component
public class MqttConsumer {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public void handleMessage(String payload) {
String timestamp = LocalDateTime.now().format(FORMATTER);
System.out.printf("[%s] Received MQTT message: %s%n", timestamp, payload);
// Additional business logic can be added here
}
}
4. 消息生产者
MqttProducer.java 文件负责向 MQTT 主题发布消息:
java
@Component
public class MqttProducer {
@Autowired
private MqttPahoMessageHandler mqttMessageHandler;
@Value("${mqtt.topic.publish}")
private String defaultPublishTopic;
@Value("${mqtt.topic.qos}")
private int defaultQos;
public void publish(String payload) {
publish(defaultPublishTopic, payload, defaultQos);
}
public void publish(String topic, String payload, int qos) {
Map<String, Object> headers = new HashMap<>();
headers.put("mqtt_topic", topic);
headers.put("mqtt_qos", qos);
Message<String> message = MessageBuilder
.withPayload(payload)
.copyHeaders(headers)
.build();
mqttMessageHandler.handleMessage(message);
}
}
5. 应用启动和运行
RabbitMqMqttIntegrationApplication.java 文件是应用的入口,负责启动应用并演示 MQTT 消息发布:
java
@SpringBootApplication
public class RabbitMqMqttIntegrationApplication implements CommandLineRunner {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Autowired
private MqttProducer mqttProducer;
public static void main(String[] args) {
SpringApplication.run(RabbitMqMqttIntegrationApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
System.out.println("RabbitMQ MQTT Integration Demo started");
System.out.println("===================================");
System.out.println("1. Make sure RabbitMQ is running and rabbitmq_mqtt plugin is enabled");
System.out.println("2. MQTT client is connecting to: tcp://localhost:1883");
System.out.println("3. Subscribed to topic: demo/subscribe");
System.out.println("4. Publishing messages to topic: demo/publish");
System.out.println("===================================");
// Publish a welcome message
String welcomeMessage = String.format("{\"message\": \"Welcome to RabbitMQ MQTT Integration\", \"timestamp\": \"%s\"}", LocalDateTime.now().format(FORMATTER));
mqttProducer.publish(welcomeMessage);
System.out.printf("[%s] Published welcome message: %s%n", LocalDateTime.now().format(FORMATTER), welcomeMessage);
// Schedule periodic message publishing every 5 seconds
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(() -> {
String periodicMessage = String.format("{\"message\": \"Periodic update\", \"counter\": %d, \"timestamp\": \"%s\"}",
System.currentTimeMillis() / 1000 % 1000, LocalDateTime.now().format(FORMATTER));
mqttProducer.publish(periodicMessage);
System.out.printf("[%s] Published periodic message: %s%n", LocalDateTime.now().format(FORMATTER), periodicMessage);
}, 5, 5, TimeUnit.SECONDS);
// Keep the application running
Runtime.getRuntime().addShutdownHook(new Thread(executor::shutdown));
}
}
6. 配置文件
application.yml 文件包含了应用的配置信息:
yaml
spring:
application:
name: rabbitmq-mqtt-integration
mqtt:
broker:
url: tcp://localhost:1883 # MQTT 服务器地址
username: guest # RabbitMQ 用户名
password: guest # RabbitMQ 密码
client-id: spring-mqtt-client # MQTT 客户端 ID
topic:
publish: demo/publish # 发布消息的主题
subscribe: demo/subscribe # 订阅的主题
qos: 1 # 服务质量级别
测试方法
您可以使用 MQTT 客户端工具(如 MQTT.fx 或 MQTT Explorer)测试应用:
- 连接到 MQTT 服务器
tcp://localhost:1883,用户名guest,密码guest - 订阅主题
demo/publish,查看应用发布的消息 - 向主题
demo/subscribe发布消息,查看应用处理消息
技术要点分析
1. Spring Integration MQTT 组件
本项目使用了 Spring Integration MQTT 模块,它提供了与 MQTT 协议交互的能力。主要组件包括:
MqttPahoClientFactory:创建 MQTT 客户端的工厂MqttPahoMessageDrivenChannelAdapter:MQTT 入站适配器,用于订阅主题并接收消息MqttPahoMessageHandler:MQTT 出站适配器,用于发布消息到主题@MessagingGateway:消息网关,提供简单的接口用于发送消息
2. MQTT 服务质量级别(QoS)
MQTT 协议定义了三种服务质量级别:
- QoS 0:最多一次,消息可能丢失
- QoS 1:至少一次,消息保证到达,但可能重复
- QoS 2:恰好一次,消息保证到达且仅到达一次
本项目使用的是 QoS 1,确保消息至少到达一次,适合大多数应用场景。
3. 消息格式
本项目使用 JSON 格式作为消息载体,包含消息内容和时间戳,便于不同系统之间的交互和解析。
应用场景
RabbitMQ MQTT 集成适用于以下场景:
- 物联网设备通信:传感器、智能设备等通过 MQTT 协议向服务器发送数据
- 实时监控系统:监控设备状态、环境数据等
- 消息通知系统:发送实时通知、预警信息等
- 微服务间通信:轻量级的服务间通信方式
总结
本文介绍了如何在 Spring Boot 应用中集成 RabbitMQ MQTT 协议,实现消息的发布与订阅。通过 Spring Integration MQTT 模块,我们可以快速构建 MQTT 客户端,实现与 RabbitMQ MQTT 服务器的通信。
项目的主要优势在于:
- 简单易用:使用 Spring Boot 和 Spring Integration,大大简化了 MQTT 客户端的开发
- 功能完整:实现了消息的发布、订阅、处理等完整功能
- 可扩展性:基于 Spring 生态系统,可以方便地集成其他组件和功能
- 可靠性:利用 RabbitMQ 的可靠性保证消息的传递
通过本文的介绍,相信您已经对 Spring Boot 集成 RabbitMQ MQTT 协议有了更深入的了解,可以在实际项目中应用这一技术来实现设备间的通信和数据交换。
代码获取
本文示例代码已上传至 GitHub,您可以通过以下链接获取: