feat(device): 添加MQTT设备在线状态管理与Redis容错机制
- 集成Spring Integration MQTT与Eclipse Paho客户端 - 添加设备在线状态填充逻辑,支持批量查询心跳数据 - 优化Redis配置,使用Lazy初始化与通用序列化器 - 增加Redis异常处理与防重复提交Fail-Open机制 - 新增Redis设备模块常量与在线状态VO - 完善MQTT与Redis集群连接配置
This commit is contained in:
117
src/main/java/com/youlai/boot/config/MqttConfig.java
Normal file
117
src/main/java/com/youlai/boot/config/MqttConfig.java
Normal file
@@ -0,0 +1,117 @@
|
||||
package com.youlai.boot.config;
|
||||
|
||||
import com.youlai.boot.config.property.MqttProperties;
|
||||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
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.inbound.MqttPahoMessageDrivenChannelAdapter;
|
||||
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
|
||||
/**
|
||||
* MQTT 配置
|
||||
* <p>
|
||||
* 基于 spring-integration-mqtt (Eclipse Paho) 实现消息的发布与订阅。
|
||||
* 通过 {@code mqtt.enabled=false} 可整体关闭 MQTT 功能。
|
||||
*
|
||||
* @author TongTongStudio
|
||||
* @since 2026/8/8
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "mqtt", name = "enabled", havingValue = "true")
|
||||
public class MqttConfig {
|
||||
|
||||
/**
|
||||
* MQTT 连接工厂
|
||||
*/
|
||||
@Bean
|
||||
public DefaultMqttPahoClientFactory mqttClientFactory(MqttProperties properties) {
|
||||
MqttConnectOptions options = new MqttConnectOptions();
|
||||
options.setServerURIs(new String[]{normalizeServerUri(properties.getUrl())});
|
||||
if (properties.getUsername() != null && !properties.getUsername().isEmpty()) {
|
||||
options.setUserName(properties.getUsername());
|
||||
}
|
||||
if (properties.getPassword() != null && !properties.getPassword().isEmpty()) {
|
||||
options.setPassword(properties.getPassword().toCharArray());
|
||||
}
|
||||
options.setConnectionTimeout(properties.getConnectionTimeout());
|
||||
options.setKeepAliveInterval(properties.getKeepAliveInterval());
|
||||
options.setAutomaticReconnect(properties.isAutomaticReconnect());
|
||||
options.setCleanSession(true);
|
||||
|
||||
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
|
||||
factory.setConnectionOptions(options);
|
||||
return factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 Broker 地址统一规范为 Paho 支持的 scheme。
|
||||
* <p>Eclipse Paho 仅内置 {@code tcp://} 与 {@code ssl://} 两种 scheme,
|
||||
* 配置中常见的 {@code mqtt://} 需转换为 {@code tcp://}(明文)或 {@code ssl://}(加密)。</p>
|
||||
*/
|
||||
private String normalizeServerUri(String uri) {
|
||||
if (uri == null || uri.isEmpty()) {
|
||||
return uri;
|
||||
}
|
||||
if (uri.startsWith("mqtt://")) {
|
||||
return "tcp://" + uri.substring("mqtt://".length());
|
||||
}
|
||||
if (uri.startsWith("mqtts://")) {
|
||||
return "ssl://" + uri.substring("mqtts://".length());
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
/* ============================ 发布 (Publish) ============================ */
|
||||
|
||||
/**
|
||||
* 发布消息的出站通道
|
||||
*/
|
||||
@Bean
|
||||
public MessageChannel mqttOutboundChannel() {
|
||||
return new DirectChannel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布消息处理器,通过 {@link org.springframework.messaging.support.MessageBuilder} 发送到出站通道即可发布
|
||||
*/
|
||||
@Bean
|
||||
@ServiceActivator(inputChannel = "mqttOutboundChannel")
|
||||
public MessageHandler mqttOutbound(DefaultMqttPahoClientFactory factory, MqttProperties properties) {
|
||||
MqttPahoMessageHandler handler = new MqttPahoMessageHandler(properties.getClientId() + "-pub", factory);
|
||||
handler.setAsync(false);
|
||||
handler.setDefaultQos(properties.getQos());
|
||||
return handler;
|
||||
}
|
||||
|
||||
/* ============================ 订阅 (Subscribe) ============================ */
|
||||
|
||||
/**
|
||||
* 订阅消息的入站通道
|
||||
*/
|
||||
@Bean
|
||||
public MessageChannel mqttInboundChannel() {
|
||||
return new DirectChannel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 入站订阅适配器:订阅 {@link MqttProperties#getTopics()} 中配置的主题
|
||||
*/
|
||||
@Bean
|
||||
public MessageProducer mqttInbound(DefaultMqttPahoClientFactory factory, MqttProperties properties) {
|
||||
String[] topics = properties.getTopics().toArray(new String[0]);
|
||||
MqttPahoMessageDrivenChannelAdapter adapter =
|
||||
new MqttPahoMessageDrivenChannelAdapter(
|
||||
properties.getClientId() + "-sub", factory, topics);
|
||||
adapter.setCompletionTimeout(5000L);
|
||||
adapter.setQos(properties.getQos());
|
||||
adapter.setOutputChannel(mqttInboundChannel());
|
||||
return adapter;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user