소스 검색

feat: 新增设备订阅相关

yangliu 4 달 전
부모
커밋
a8a414df10
68개의 변경된 파일11개의 추가작업 그리고 5690개의 파일을 삭제
  1. 2 0
      device-service-application/src/main/java/com/hfln/device/application/service/DeviceMonitorServiceImpl.java
  2. 1 1
      device-service-application/src/main/java/com/hfln/device/application/service/impl/DeviceEventServiceExtendImpl.java
  3. 1 1
      device-service-application/src/main/java/com/hfln/device/application/service/impl/DeviceEventServiceImpl.java
  4. 0 90
      device-service-domain/src/main/java/com/hfln/device/domain/gateway/BatchMqttGateway.java
  5. 3 1
      device-service-infrastructure/src/main/java/com/hfln/device/infrastructure/config/MqttConfig.java
  6. 0 237
      device-service-infrastructure/src/main/java/com/hfln/device/infrastructure/gateway/impl/BatchMqttGatewayImpl.java
  7. 3 5
      device-service-infrastructure/src/main/java/com/hfln/device/infrastructure/gateway/impl/DeviceGatewayImpl.java
  8. 0 234
      mqtt-spring-boot-starter/README.md
  9. 0 1
      mqtt-spring-boot-starter/mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/exception/MqttExceptionHandler.java
  10. 0 155
      mqtt-spring-boot-starter/pom.xml
  11. 0 18
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/annotation/MqttSubscribe.java
  12. 0 48
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/annotation/MqttSubscriber.java
  13. 0 175
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/BatchResult.java
  14. 0 34
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/MergeStrategy.java
  15. 0 157
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/MqttBatchOperations.java
  16. 0 41
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/SplitStrategy.java
  17. 0 0
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/config/MqttBatchAutoConfiguration.java
  18. 0 107
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/impl/DelimiterMergeStrategy.java
  19. 0 57
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/impl/JsonArrayMergeStrategy.java
  20. 0 180
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/impl/JsonSplitStrategy.java
  21. 0 142
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/impl/MqttBatchTemplate.java
  22. 0 148
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/impl/SizeLimitSplitStrategy.java
  23. 0 256
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/config/MqttAutoConfiguration.java
  24. 0 49
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/config/MqttClientConfig.java
  25. 0 170
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/config/MqttProperties.java
  26. 0 292
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/connection/MqttReconnectManager.java
  27. 0 80
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/converter/JsonMessageConverter.java
  28. 0 27
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/converter/MessageConverter.java
  29. 0 28
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/exception/MqttExceptionHandler.java
  30. 0 225
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/gateway/DefaultMqttGateway.java
  31. 0 132
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/gateway/MqttGateway.java
  32. 0 0
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/handler/GenericMqttMessageHandler.java
  33. 0 22
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/handler/MqttMessageHandler.java
  34. 0 102
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/handler/MqttMessageRouter.java
  35. 0 120
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/handler/MqttSubscribeProcessor.java
  36. 0 243
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/handler/MqttSubscriberProcessor.java
  37. 0 18
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/handler/MqttTopicHandler.java
  38. 0 33
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/interceptor/DefaultMqttMessageInterceptor.java
  39. 0 67
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/interceptor/MqttMessageInterceptor.java
  40. 0 25
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/listener/DefaultMqttConnectionListener.java
  41. 0 17
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/listener/DefaultMqttMessageListener.java
  42. 0 47
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/listener/MqttConnectionListener.java
  43. 0 18
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/listener/MqttMessageListener.java
  44. 0 540
      mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/template/MqttTemplate.java
  45. BIN
      mqtt-spring-boot-starter/src/main/resources/META-INF/spring.factories
  46. 0 1
      mqtt-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  47. BIN
      mqtt-spring-boot-starter/src/main/resources/docs/MQTT批量操作使用指南.md
  48. 0 61
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/batch/BatchResultTest.java
  49. 0 82
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/batch/MqttBatchOperationsTest.java
  50. 0 10
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/batch/MqttBatchTemplateTest.java
  51. 0 55
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/batch/impl/DelimiterMergeStrategyTest.java
  52. 0 61
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/batch/impl/JsonArrayMergeStrategyTest.java
  53. 0 70
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/batch/impl/JsonSplitStrategyTest.java
  54. 0 65
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/batch/impl/SizeLimitSplitStrategyTest.java
  55. 0 57
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/config/MqttAutoConfigurationTest.java
  56. 0 56
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/config/MqttPropertiesTest.java
  57. 0 78
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/converter/JsonMessageConverterTest.java
  58. 0 44
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/exception/MqttExceptionHandlerTest.java
  59. 0 155
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/gateway/DefaultMqttGatewayTest.java
  60. 0 53
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/handler/MqttMessageHandlerTest.java
  61. 0 68
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/handler/MqttMessageRouterTest.java
  62. 0 114
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/handler/MqttSubscribeProcessorTest.java
  63. 0 153
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/handler/MqttSubscriberProcessorTest.java
  64. 0 35
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/handler/MqttTopicHandlerTest.java
  65. 0 27
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/listener/DefaultMqttConnectionListenerTest.java
  66. 0 31
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/listener/DefaultMqttMessageListenerTest.java
  67. 0 70
      mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/template/MqttTemplateTest.java
  68. 1 1
      pom.xml

+ 2 - 0
device-service-application/src/main/java/com/hfln/device/application/service/DeviceMonitorServiceImpl.java

@@ -12,6 +12,7 @@ import com.hfln.device.domain.service.DeviceMonitorService;
 import com.hfln.device.domain.service.DeviceService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Service;
 
 import java.time.Instant;
@@ -38,6 +39,7 @@ public class DeviceMonitorServiceImpl implements DeviceMonitorService {
     private MqttGateway mqttGateway;
     
     @Autowired
+    @Qualifier("deviceEventServiceExtendImpl")
     private DeviceEventServiceExtend eventService;
     
     /**

+ 1 - 1
device-service-application/src/main/java/com/hfln/device/application/service/impl/DeviceEventServiceExtendImpl.java

@@ -12,7 +12,7 @@ import org.springframework.stereotype.Service;
 /**
  * 设备事件服务扩展实现
  */
-@Service
+@Service("deviceEventServiceExtendImpl")
 public class DeviceEventServiceExtendImpl implements DeviceEventServiceExtend {
 
     private static final Logger log = LoggerFactory.getLogger(DeviceEventServiceExtendImpl.class);

+ 1 - 1
device-service-application/src/main/java/com/hfln/device/application/service/impl/DeviceEventServiceImpl.java

@@ -28,7 +28,7 @@ import java.util.Optional;
  * 设备事件服务实现类
  * 应用层服务,负责协调领域服务和基础设施服务
  */
-@Service
+@Service("deviceEventServiceImpl")
 public class DeviceEventServiceImpl implements DeviceEventService {
 
     private static final Logger log = LoggerFactory.getLogger(DeviceEventServiceImpl.class);

+ 0 - 90
device-service-domain/src/main/java/com/hfln/device/domain/gateway/BatchMqttGateway.java

@@ -1,90 +0,0 @@
-package com.hfln.device.domain.gateway;
-
-import cn.hfln.framework.mqtt.batch.BatchResult;
-
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-
-/**
- * 批量MQTT网关接口
- * 提供批量发送MQTT消息的功能
- */
-public interface BatchMqttGateway {
-
-    /**
-     * 向多个设备发送命令
-     *
-     * @param deviceIds 设备ID列表
-     * @param command   命令名称
-     * @param params    命令参数
-     * @return 批量操作结果
-     */
-    BatchResult sendCommandToMultipleDevices(List<String> deviceIds, String command, Map<String, Object> params);
-
-    /**
-     * 向多个设备发送重启命令
-     *
-     * @param deviceIds 设备ID列表
-     * @return 批量操作结果
-     */
-    BatchResult sendRebootCommandToDevices(List<String> deviceIds);
-
-    /**
-     * 向多个设备发送重置命令
-     *
-     * @param deviceIds 设备ID列表
-     * @return 批量操作结果
-     */
-    BatchResult sendResetCommandToDevices(List<String> deviceIds);
-
-    /**
-     * 向多个设备发送参数更新
-     *
-     * @param deviceIds  设备ID列表
-     * @param mountPlain 安装平面
-     * @param area       区域
-     * @param height     高度
-     * @return 批量操作结果
-     */
-    BatchResult sendParamUpdateToDevices(List<String> deviceIds, String mountPlain, String area, Float height);
-
-    /**
-     * 向多个设备发送网络配置更新
-     *
-     * @param deviceIds 设备ID列表
-     * @param ssid      WiFi名称
-     * @param password  WiFi密码
-     * @return 批量操作结果
-     */
-    BatchResult sendNetworkUpdateToDevices(List<String> deviceIds, String ssid, String password);
-
-    /**
-     * 向多个设备发布状态消息
-     *
-     * @param deviceIds 设备ID列表
-     * @param status    状态
-     * @param data      数据
-     * @return 批量操作结果
-     */
-    BatchResult publishStatusToDevices(List<String> deviceIds, String status, Map<String, Object> data);
-
-    /**
-     * 异步向多个设备发送命令
-     *
-     * @param deviceIds 设备ID列表
-     * @param command   命令名称
-     * @param params    命令参数
-     * @return 异步操作结果
-     */
-    CompletableFuture<BatchResult> sendCommandToMultipleDevicesAsync(List<String> deviceIds, String command, Map<String, Object> params);
-
-    /**
-     * 发送批量通知消息
-     *
-     * @param topic    主题
-     * @param messages 消息列表
-     * @return 批量操作结果
-     */
-    BatchResult sendBulkNotification(String topic, List<Map<String, Object>> messages);
-} 

+ 3 - 1
device-service-infrastructure/src/main/java/com/hfln/device/infrastructure/config/MqttConfig.java

@@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Primary;
@@ -26,9 +27,10 @@ import com.hfln.device.common.constant.mqtt.topic.MqttTopics;
  */
 @Configuration
 @Slf4j
+@ConditionalOnProperty(prefix = "mqtt", name = "enabled", havingValue = "true", matchIfMissing = true)
 public class MqttConfig {
 
-    @Value("${mqtt.server.uri:tcp://localhost:1883}")
+    @Value("${mqtt.broker:tcp://localhost:1883}")
     private String serverUri;
     
     @Value("${mqtt.client.id:device-service-}")

+ 0 - 237
device-service-infrastructure/src/main/java/com/hfln/device/infrastructure/gateway/impl/BatchMqttGatewayImpl.java

@@ -1,237 +0,0 @@
-package com.hfln.device.infrastructure.gateway.impl;
-
-import cn.hfln.framework.mqtt.batch.BatchResult;
-import cn.hfln.framework.mqtt.batch.MergeStrategy;
-import cn.hfln.framework.mqtt.batch.MqttBatchOperations;
-import cn.hfln.framework.mqtt.batch.SplitStrategy;
-import cn.hfln.framework.mqtt.batch.impl.DelimiterMergeStrategy;
-import cn.hfln.framework.mqtt.batch.impl.JsonArrayMergeStrategy;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.hfln.device.domain.entity.Device;
-import com.hfln.device.domain.gateway.BatchMqttGateway;
-import com.hfln.device.domain.constant.DeviceConstants;
-import com.hfln.device.domain.constant.TopicConstants;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-import java.util.*;
-import java.util.concurrent.CompletableFuture;
-import java.util.stream.Collectors;
-
-/**
- * 批量MQTT网关实现类
- * 使用MQTT批量操作功能实现批量消息发送
- */
-@Slf4j
-@Component
-public class BatchMqttGatewayImpl implements BatchMqttGateway {
-
-    @Autowired
-    private MqttBatchOperations mqttBatchOperations;
-    
-    @Autowired
-    private ObjectMapper objectMapper;
-    
-    @Autowired
-    private JsonArrayMergeStrategy jsonArrayMergeStrategy;
-    
-    @Autowired
-    private DelimiterMergeStrategy newLineMergeStrategy;
-    
-    @Value("${mqtt.qos:1}")
-    private int qos;
-    
-    @Value("${mqtt.retain:false}")
-    private boolean retain;
-
-    @Override
-    public BatchResult sendCommandToMultipleDevices(List<String> deviceIds, String command, Map<String, Object> params) {
-        if (deviceIds == null || deviceIds.isEmpty()) {
-            log.warn("设备ID列表为空,无法发送命令");
-            return new BatchResult();
-        }
-        
-        // 构建每个设备的主题和消息内容
-        Map<String, Object> topicPayloads = new HashMap<>(deviceIds.size());
-        
-        for (String deviceId : deviceIds) {
-            String topic = TopicConstants.getDeviceSpecificTopic(deviceId, "command");
-            
-            Map<String, Object> payload = new HashMap<>();
-            payload.put("deviceId", deviceId);
-            payload.put("command", command);
-            if (params != null) {
-                payload.put("params", params);
-            }
-            payload.put("timestamp", System.currentTimeMillis());
-            
-            topicPayloads.put(topic, payload);
-        }
-        
-        // 批量发送JSON消息到不同主题
-        BatchResult result = mqttBatchOperations.batchSendJsonToMultipleTopics(topicPayloads, qos, retain);
-        
-        // 记录发送结果
-        if (result.isAllSucceeded()) {
-            log.info("成功向{}个设备发送{}命令", deviceIds.size(), command);
-        } else {
-            log.warn("向设备发送{}命令部分失败,总数: {}, 成功: {}, 失败: {}", 
-                    command, result.getTotalCount(), result.getSuccessCount(), result.getFailureCount());
-            
-            // 记录失败的设备ID
-            List<String> failedDeviceIds = result.getFailedResults().stream()
-                    .map(r -> r.getTopic().split("/")[1]) // 从主题中提取设备ID
-                    .collect(Collectors.toList());
-            
-            log.warn("发送失败的设备: {}", failedDeviceIds);
-        }
-        
-        return result;
-    }
-    
-    @Override
-    public BatchResult sendRebootCommandToDevices(List<String> deviceIds) {
-        return sendCommandToMultipleDevices(deviceIds, "reboot", null);
-    }
-    
-    @Override
-    public BatchResult sendResetCommandToDevices(List<String> deviceIds) {
-        return sendCommandToMultipleDevices(deviceIds, "reset", null);
-    }
-    
-    @Override
-    public BatchResult sendParamUpdateToDevices(List<String> deviceIds, String mountPlain, String area, Float height) {
-        Map<String, Object> params = new HashMap<>();
-        if (mountPlain != null) {
-            params.put("mountPlain", mountPlain);
-        }
-        if (area != null) {
-            params.put("area", area);
-        }
-        if (height != null) {
-            params.put("height", height);
-        }
-        
-        return sendCommandToMultipleDevices(deviceIds, "setParam", params);
-    }
-    
-    @Override
-    public BatchResult sendNetworkUpdateToDevices(List<String> deviceIds, String ssid, String password) {
-        Map<String, Object> params = new HashMap<>();
-        params.put("ssid", ssid);
-        params.put("password", password);
-        
-        return sendCommandToMultipleDevices(deviceIds, "updateNetwork", params);
-    }
-    
-    @Override
-    public BatchResult publishStatusToDevices(List<String> deviceIds, String status, Map<String, Object> data) {
-        if (deviceIds == null || deviceIds.isEmpty()) {
-            log.warn("设备ID列表为空,无法发送状态消息");
-            return new BatchResult();
-        }
-        
-        // 构建每个设备的消息内容
-        List<Map<String, Object>> payloads = new ArrayList<>(deviceIds.size());
-        
-        for (String deviceId : deviceIds) {
-            Map<String, Object> payload = new HashMap<>(data != null ? data : new HashMap<>());
-            payload.put("deviceId", deviceId);
-            payload.put("status", status);
-            payload.put("timestamp", System.currentTimeMillis());
-            
-            payloads.add(payload);
-        }
-        
-        // 批量发送JSON消息到同一主题
-        BatchResult result = mqttBatchOperations.batchSendJson(DeviceConstants.MqttConstant.TOPIC_DAS_STATUS, 
-                payloads, qos, retain);
-        
-        // 记录发送结果
-        if (result.isAllSucceeded()) {
-            log.info("成功向{}个设备发送状态消息: {}", deviceIds.size(), status);
-        } else {
-            log.warn("向设备发送状态消息部分失败,总数: {}, 成功: {}, 失败: {}", 
-                    result.getTotalCount(), result.getSuccessCount(), result.getFailureCount());
-        }
-        
-        return result;
-    }
-    
-    @Override
-    public CompletableFuture<BatchResult> sendCommandToMultipleDevicesAsync(
-            List<String> deviceIds, String command, Map<String, Object> params) {
-        
-        if (deviceIds == null || deviceIds.isEmpty()) {
-            log.warn("设备ID列表为空,无法发送命令");
-            return CompletableFuture.completedFuture(new BatchResult());
-        }
-        
-        // 构建每个设备的主题
-        List<String> topics = deviceIds.stream()
-                .map(id -> TopicConstants.getDeviceSpecificTopic(id, "command"))
-                .collect(Collectors.toList());
-        
-        // 构建每个设备的消息内容
-        List<Map<String, Object>> payloads = new ArrayList<>(deviceIds.size());
-        
-        for (String deviceId : deviceIds) {
-            Map<String, Object> payload = new HashMap<>();
-            payload.put("deviceId", deviceId);
-            payload.put("command", command);
-            if (params != null) {
-                payload.put("params", params);
-            }
-            payload.put("timestamp", System.currentTimeMillis());
-            
-            payloads.add(payload);
-        }
-        
-        // 将主题和消息内容组合为Map
-        Map<String, Object> topicPayloads = new HashMap<>(deviceIds.size());
-        for (int i = 0; i < deviceIds.size(); i++) {
-            topicPayloads.put(topics.get(i), payloads.get(i));
-        }
-        
-        // 异步批量发送JSON消息到不同主题
-        CompletableFuture<BatchResult> future = CompletableFuture.supplyAsync(() -> 
-                mqttBatchOperations.batchSendJsonToMultipleTopics(topicPayloads, qos, retain));
-        
-        // 添加回调处理结果
-        future.thenAccept(result -> {
-            if (result.isAllSucceeded()) {
-                log.info("成功向{}个设备异步发送{}命令", deviceIds.size(), command);
-            } else {
-                log.warn("向设备异步发送{}命令部分失败,总数: {}, 成功: {}, 失败: {}", 
-                        command, result.getTotalCount(), result.getSuccessCount(), result.getFailureCount());
-            }
-        }).exceptionally(e -> {
-            log.error("向设备异步发送{}命令时发生异常", command, e);
-            return null;
-        });
-        
-        return future;
-    }
-    
-    @Override
-    public BatchResult sendBulkNotification(String topic, List<Map<String, Object>> messages) {
-        // 使用JSON数组合并策略将多个消息合并为一个JSON数组
-        return mqttBatchOperations.sendWithMergeStrategy(topic, 
-                messages.stream().map(this::toJsonString).collect(Collectors.toList()),
-                jsonArrayMergeStrategy);
-    }
-    
-    /**
-     * 将对象转换为JSON字符串
-     */
-    private String toJsonString(Object obj) {
-        try {
-            return objectMapper.writeValueAsString(obj);
-        } catch (Exception e) {
-            log.error("JSON序列化失败", e);
-            return "{}";
-        }
-    }
-} 

+ 3 - 5
device-service-infrastructure/src/main/java/com/hfln/device/infrastructure/gateway/impl/DeviceGatewayImpl.java

@@ -11,6 +11,7 @@ import com.hfln.device.common.request.device.DeviceBandingParams;
 import com.hfln.device.common.request.device.DeviceListParams;
 import com.hfln.device.common.request.device.DeviceLocationParams;
 import com.hfln.device.common.request.event.EventListParams;
+import com.hfln.device.common.util.JsonUtil;
 import com.hfln.device.common.vo.PageRecord;
 import com.hfln.device.domain.entity.Device;
 import com.hfln.device.domain.entity.DeviceBehavior;
@@ -80,9 +81,6 @@ public class DeviceGatewayImpl implements DeviceGateway {
     private DeviceBehaviorService deviceBehaviorService;
     
     @Autowired
-    private com.hfln.device.common.util.JsonUtil jsonUtil;
-    
-    @Autowired
     private org.springframework.jdbc.core.JdbcTemplate jdbcTemplate;
 
     @Autowired
@@ -393,7 +391,7 @@ public class DeviceGatewayImpl implements DeviceGateway {
             log.info("保存设备: {}", device.getDevId());
             
             // 参数校验
-            if (device == null || StringUtils.isBlank(device.getDevId())) {
+            if (StringUtils.isBlank(device.getDevId())) {
                 log.warn("设备或设备ID为空");
                 return null;
             }
@@ -1171,7 +1169,7 @@ public class DeviceGatewayImpl implements DeviceGateway {
                     .createTime(System.currentTimeMillis())
                     .updateTime(System.currentTimeMillis())
                     .timestamp(System.currentTimeMillis())
-                    .extraData(jsonUtil.toJsonString(data))
+                    .extraData(JsonUtil.toJsonString(data))
                     .build();
             
             // 这里应该将行为数据保存到数据库

+ 0 - 234
mqtt-spring-boot-starter/README.md

@@ -1,234 +0,0 @@
-# MQTT Spring Boot Starter
-
-一个基于 Spring Boot 的 MQTT 客户端启动器,提供了简单易用的 MQTT 消息发布订阅功能。
-
-## 特性
-
-- 支持 MQTT 消息的发布和订阅
-- 支持通配符主题订阅(+ 和 #)
-- 支持 JSON 消息的自动转换
-- 支持消息拦截器
-- 支持连接状态监听
-- 支持消息监听器
-- 支持 SSL/TLS 加密连接
-- 支持自动重连
-- 支持消息持久化
-
-## 快速开始
-
-### 1. 添加依赖
-
-```xml
-<dependency>
-    <groupId>cn.hfln.framework</groupId>
-    <artifactId>mqtt-spring-boot-starter</artifactId>
-    <version>${latest.version}</version>
-</dependency>
-```
-
-### 2. 配置属性
-
-在 `application.yml` 中添加以下配置:
-
-```yaml
-mqtt:
-  enabled: true
-  broker: tcp://localhost:1883
-  client-id: ${spring.application.name}
-  username: your-username
-  password: your-password
-  timeout: 30
-  keepalive: 60
-  clean-session: true
-  automatic-reconnect: true
-  max-reconnect-delay: 10000
-  connection-timeout: 30
-  max-message-size: 1048576
-  ssl: false
-  # SSL 配置(如果需要)
-  ssl-ca-path: /path/to/ca.crt
-  ssl-client-cert-path: /path/to/client.crt
-  ssl-client-key-path: /path/to/client.key
-  ssl-client-key-password: your-key-password
-```
-
-### 3. 使用示例
-
-#### 3.1 发送消息
-
-```java
-@Autowired
-private MqttTemplate mqttTemplate;
-
-// 发送字符串消息
-mqttTemplate.send("test/topic", "Hello MQTT!");
-
-// 发送 JSON 消息
-TestMessage message = new TestMessage("test", 123);
-mqttTemplate.sendJson("test/json", message);
-```
-
-#### 3.2 订阅消息
-
-```java
-@Component
-public class MqttMessageHandler {
-    
-    @MqttSubscribe(topic = "test/+/topic")
-    public void handleStringMessage(String message) {
-        System.out.println("Received message: " + message);
-    }
-    
-    @MqttSubscribe(topic = "test/json")
-    public void handleJsonMessage(TestMessage message) {
-        System.out.println("Received JSON message: " + message);
-    }
-}
-```
-
-#### 3.3 自定义消息拦截器
-
-```java
-@Component
-public class CustomMqttMessageInterceptor implements MqttMessageInterceptor {
-    
-    @Override
-    public boolean preSend(String topic, MqttMessage message) {
-        // 发送消息前的处理
-        return true;
-    }
-    
-    @Override
-    public void postSend(String topic, MqttMessage message) {
-        // 发送消息后的处理
-    }
-    
-    @Override
-    public boolean preReceive(String topic, MqttMessage message) {
-        // 接收消息前的处理
-        return true;
-    }
-    
-    @Override
-    public void postReceive(String topic, MqttMessage message) {
-        // 接收消息后的处理
-    }
-}
-```
-
-#### 3.4 连接状态监听
-
-```java
-@Component
-public class CustomMqttConnectionListener implements MqttConnectionListener {
-    
-    @Override
-    public void onConnected() {
-        System.out.println("MQTT client connected");
-    }
-    
-    @Override
-    public void onDisconnected() {
-        System.out.println("MQTT client disconnected");
-    }
-    
-    @Override
-    public void onConnectionLost(Throwable cause) {
-        System.out.println("MQTT connection lost: " + cause.getMessage());
-    }
-}
-```
-
-## 高级特性
-
-### 1. 通配符主题
-
-支持 MQTT 通配符主题订阅:
-
-- `+`:匹配单层任意字符
-- `#`:匹配多层任意字符
-
-示例:
-```java
-@MqttSubscribe(topic = "test/+/topic")  // 匹配 test/1/topic, test/2/topic 等
-@MqttSubscribe(topic = "test/#")        // 匹配 test/ 下的所有主题
-```
-
-### 2. 消息转换
-
-支持自动的 JSON 消息转换:
-
-```java
-@MqttSubscribe(topic = "test/json")
-public void handleJsonMessage(TestMessage message) {
-    // message 会自动从 JSON 转换为 TestMessage 对象
-}
-```
-
-### 3. 异步消息发送
-
-支持异步消息发送:
-
-```java
-mqttTemplate.send("test/topic", "Hello MQTT!")
-    .thenRun(() -> System.out.println("Message sent successfully"))
-    .exceptionally(throwable -> {
-        System.out.println("Failed to send message: " + throwable.getMessage());
-        return null;
-    });
-```
-
-## 配置说明
-
-| 配置项 | 说明 | 默认值 |
-|--------|------|--------|
-| mqtt.enabled | 是否启用 MQTT | true |
-| mqtt.broker | MQTT 服务器地址 | - |
-| mqtt.client-id | 客户端 ID | ${spring.application.name} |
-| mqtt.username | 用户名 | - |
-| mqtt.password | 密码 | - |
-| mqtt.timeout | 超时时间(秒) | 30 |
-| mqtt.keepalive | 保活时间(秒) | 60 |
-| mqtt.clean-session | 是否清除会话 | true |
-| mqtt.automatic-reconnect | 是否自动重连 | true |
-| mqtt.max-reconnect-delay | 最大重连延迟(毫秒) | 10000 |
-| mqtt.connection-timeout | 连接超时时间(秒) | 30 |
-| mqtt.max-message-size | 最大消息大小(字节) | 1048576 |
-| mqtt.ssl | 是否启用 SSL | false |
-| mqtt.ssl-ca-path | CA 证书路径 | - |
-| mqtt.ssl-client-cert-path | 客户端证书路径 | - |
-| mqtt.ssl-client-key-path | 客户端密钥路径 | - |
-| mqtt.ssl-client-key-password | 客户端密钥密码 | - |
-
-## 注意事项
-
-1. 确保 MQTT 服务器地址配置正确
-2. 如果使用 SSL/TLS,确保证书配置正确
-3. 建议在生产环境中启用自动重连功能
-4. 注意设置合适的消息大小限制
-5. 建议使用唯一的客户端 ID,避免冲突
-
-## 常见问题
-
-1. 连接失败
-   - 检查服务器地址是否正确
-   - 检查用户名密码是否正确
-   - 检查网络连接是否正常
-
-2. 消息发送失败
-   - 检查客户端是否已连接
-   - 检查主题格式是否正确
-   - 检查消息大小是否超限
-
-3. 消息接收失败
-   - 检查订阅主题是否正确
-   - 检查消息格式是否匹配
-   - 检查处理方法参数类型是否正确
-
-## 贡献指南
-
-欢迎提交 Issue 和 Pull Request。
-
-## 许可证
-
-本项目采用 MIT 许可证。 

+ 0 - 1
mqtt-spring-boot-starter/mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/exception/MqttExceptionHandler.java

@@ -1 +0,0 @@
-�

+ 0 - 155
mqtt-spring-boot-starter/pom.xml

@@ -1,155 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>com.hfln.device</groupId>
-        <artifactId>hfln-device-service</artifactId>
-        <version>1.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <groupId>cn.hfln.framework</groupId>
-    <artifactId>mqtt-spring-boot-starter</artifactId>
-
-    <properties>
-        <maven.compiler.source>8</maven.compiler.source>
-        <maven.compiler.target>8</maven.compiler.target>
-        <spring-integration.version>5.5.14</spring-integration.version>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.eclipse.paho</groupId>
-            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
-            <version>1.2.5</version>
-        </dependency>
-
-        <!--        <dependency>-->
-        <!--            <groupId>com.hivemq</groupId>-->
-        <!--            <artifactId>hivemq-mqtt-client</artifactId>-->
-        <!--            <version>1.2.1</version>-->
-        <!--        </dependency>-->
-
-        <!-- Spring Integration MQTT -->
-        <dependency>
-            <groupId>org.springframework.integration</groupId>
-            <artifactId>spring-integration-mqtt</artifactId>
-            <version>${spring-integration.version}</version>
-        </dependency>
-
-        <!-- Spring Integration Core -->
-        <dependency>
-            <groupId>org.springframework.integration</groupId>
-            <artifactId>spring-integration-core</artifactId>
-            <version>${spring-integration.version}</version>
-        </dependency>
-
-        <!-- Lombok -->
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- slf4j: 2.x -->
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <version>1.7.36</version>
-        </dependency>
-
-        <!-- spring-boot: 2.x -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-autoconfigure</artifactId>
-        </dependency>
-        <!-- optional: configuration-processor -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-configuration-processor</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <!-- optional: jackson -->
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.junit.jupiter</groupId>
-            <artifactId>junit-jupiter</artifactId>
-            <version>5.9.0</version>
-            <optional>true</optional>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <!-- Spring Boot Test -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-        
-        <!-- JUnit Jupiter -->
-        <dependency>
-            <groupId>org.junit.jupiter</groupId>
-            <artifactId>junit-jupiter-api</artifactId>
-            <version>5.6.3</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.junit.jupiter</groupId>
-            <artifactId>junit-jupiter-engine</artifactId>
-            <version>5.6.3</version>
-            <scope>test</scope>
-        </dependency>
-
-        <!-- Logging -->
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-            <version>1.2.11</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-core</artifactId>
-            <version>1.2.11</version>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-            <version>4.5.1</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-junit-jupiter</artifactId>
-            <version>4.5.1</version>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>net.bytebuddy</groupId>
-            <artifactId>byte-buddy</artifactId>
-            <version>1.12.10</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>net.bytebuddy</groupId>
-            <artifactId>byte-buddy-agent</artifactId>
-            <version>1.12.10</version>
-            <scope>test</scope>
-        </dependency>
-
-    </dependencies>
-</project>

+ 0 - 18
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/annotation/MqttSubscribe.java

@@ -1,18 +0,0 @@
-package cn.hfln.framework.mqtt.annotation;
-
-import java.lang.annotation.*;
-
-@Target({ElementType.METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-public @interface MqttSubscribe {
-    /**
-     * MQTT主题
-     */
-    String topic();
-
-    /**
-     * QoS级别 (0, 1, 2)
-     */
-    int qos() default 0;
-} 

+ 0 - 48
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/annotation/MqttSubscriber.java

@@ -1,48 +0,0 @@
-package cn.hfln.framework.mqtt.annotation;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * MQTT消息订阅注解
- * 用于标记处理MQTT消息的方法
- */
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-public @interface MqttSubscriber {
-    
-    /**
-     * MQTT主题,支持通配符
-     * 例如:/dev/+/report_device_info
-     */
-    String topic();
-    
-    /**
-     * QoS级别
-     * 0: 最多一次传送 (At most once)
-     * 1: 至少一次传送 (At least once)
-     * 2: 正好一次传送 (Exactly once)
-     */
-    int qos() default 1;
-    
-    /**
-     * 是否共享订阅
-     * 使用共享订阅时,相同clientId的客户端只会有一个收到消息
-     */
-    boolean shared() default false;
-    
-    /**
-     * 共享订阅组名
-     * 当shared为true时生效
-     */
-    String group() default "default";
-    
-    /**
-     * 描述信息
-     */
-    String desc() default "";
-} 

+ 0 - 175
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/BatchResult.java

@@ -1,175 +0,0 @@
-package cn.hfln.framework.mqtt.batch;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * 批量操作结果类
- * 用于表示批量发送或订阅操作的结果
- */
-public class BatchResult {
-    private boolean allSucceeded;
-    private int totalCount;
-    private int successCount;
-    private int failureCount;
-    private List<OperationResult> results;
-
-    public BatchResult() {
-        this.results = new ArrayList<>();
-    }
-
-    /**
-     * 添加一个操作结果
-     * @param result 操作结果
-     */
-    public void addResult(OperationResult result) {
-        this.results.add(result);
-        this.totalCount++;
-        if (result.isSuccess()) {
-            this.successCount++;
-        } else {
-            this.failureCount++;
-        }
-        this.allSucceeded = (this.failureCount == 0);
-    }
-
-    /**
-     * 批量添加操作结果
-     * @param results 操作结果列表
-     */
-    public void addResults(List<OperationResult> results) {
-        for (OperationResult result : results) {
-            addResult(result);
-        }
-    }
-
-    /**
-     * 获取所有操作结果
-     * @return 操作结果列表
-     */
-    public List<OperationResult> getResults() {
-        return Collections.unmodifiableList(results);
-    }
-
-    /**
-     * 是否全部成功
-     * @return 如果所有操作都成功则返回true
-     */
-    public boolean isAllSucceeded() {
-        return allSucceeded;
-    }
-
-    /**
-     * 获取总操作数
-     * @return 总操作数
-     */
-    public int getTotalCount() {
-        return totalCount;
-    }
-
-    /**
-     * 获取成功操作数
-     * @return 成功操作数
-     */
-    public int getSuccessCount() {
-        return successCount;
-    }
-
-    /**
-     * 获取失败操作数
-     * @return 失败操作数
-     */
-    public int getFailureCount() {
-        return failureCount;
-    }
-
-    /**
-     * 获取成功率
-     * @return 成功率(0-1.0之间的小数)
-     */
-    public double getSuccessRate() {
-        return totalCount == 0 ? 0 : (double) successCount / totalCount;
-    }
-
-    /**
-     * 获取失败的操作结果
-     * @return 失败的操作结果列表
-     */
-    public List<OperationResult> getFailedResults() {
-        List<OperationResult> failedResults = new ArrayList<>();
-        for (OperationResult result : results) {
-            if (!result.isSuccess()) {
-                failedResults.add(result);
-            }
-        }
-        return failedResults;
-    }
-
-    /**
-     * 单个操作结果
-     */
-    public static class OperationResult {
-        private final boolean success;
-        private final String topic;
-        private final String payload;
-        private final String errorMessage;
-        private final Throwable exception;
-
-        public OperationResult(boolean success, String topic, String payload) {
-            this(success, topic, payload, null, null);
-        }
-
-        public OperationResult(boolean success, String topic, String payload, String errorMessage, Throwable exception) {
-            this.success = success;
-            this.topic = topic;
-            this.payload = payload;
-            this.errorMessage = errorMessage;
-            this.exception = exception;
-        }
-
-        public boolean isSuccess() {
-            return success;
-        }
-
-        public String getTopic() {
-            return topic;
-        }
-
-        public String getPayload() {
-            return payload;
-        }
-
-        public String getErrorMessage() {
-            return errorMessage;
-        }
-
-        public Throwable getException() {
-            return exception;
-        }
-    }
-
-    /**
-     * 创建成功的操作结果
-     * @param topic   主题
-     * @param payload 消息内容
-     * @return 操作结果
-     */
-    public static OperationResult success(String topic, String payload) {
-        return new OperationResult(true, topic, payload);
-    }
-
-    /**
-     * 创建失败的操作结果
-     * @param topic        主题
-     * @param payload      消息内容
-     * @param errorMessage 错误消息
-     * @param exception    异常
-     * @return 操作结果
-     */
-    public static OperationResult failure(String topic, String payload, String errorMessage, Throwable exception) {
-        return new OperationResult(false, topic, payload, errorMessage, exception);
-    }
-} 
-
-

+ 0 - 34
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/MergeStrategy.java

@@ -1,34 +0,0 @@
-package cn.hfln.framework.mqtt.batch;
-
-import java.util.List;
-
-/**
- * 娑堟伅鍚堝苟绛栫暐鎺ュ彛
- * 鐢ㄤ簬灏嗗涓皬娑堟伅鍚堝苟涓轰竴涓ぇ娑堟伅锛屼互鍑忓皯缃戠粶寮€閿€
- */
-public interface MergeStrategy {
-
-    /**
-     * 鍚堝苟澶氫釜娑堟伅涓轰竴涓?
-     *
-     * @param payloads 寰呭悎骞剁殑娑堟伅鍒楄〃
-     * @return 鍚堝苟鍚庣殑娑堟伅
-     */
-    String merge(List<String> payloads);
-
-    /**
-     * 鑾峰彇鍚堝苟绛栫暐鐨勫悕绉?
-     *
-     * @return 绛栫暐鍚嶇О
-     */
-    String getName();
-
-    /**
-     * 鑾峰彇鍚堝苟绛栫暐鐨勬弿杩?
-     *
-     * @return 绛栫暐鎻忚堪
-     */
-    String getDescription();
-} 
-
-

+ 0 - 157
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/MqttBatchOperations.java

@@ -1,157 +0,0 @@
-package cn.hfln.framework.mqtt.batch;
-
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-
-/**
- * MQTT鎵归噺鎿嶄綔鎺ュ彛
- * 鎻愪緵鎵归噺鍙戦€佹秷鎭€佽闃呬富棰樼瓑鍔熻兘
- */
-public interface MqttBatchOperations {
-
-    /**
-     * 鎵归噺鍙戦€佹秷鎭埌鍚屼竴涓婚
-     *
-     * @param topic    涓婚
-     * @param payloads 娑堟伅鍐呭鍒楄〃
-     * @return 鎵归噺鎿嶄綔缁撴灉
-     */
-    BatchResult batchSend(String topic, List<String> payloads);
-
-    /**
-     * 鎵归噺鍙戦€佹秷鎭埌鍚屼竴涓婚锛堟寚瀹歈oS鍜屼繚鐣欐爣蹇楋級
-     *
-     * @param topic    涓婚
-     * @param payloads 娑堟伅鍐呭鍒楄〃
-     * @param qos      QoS绾у埆
-     * @param retain   鏄惁淇濈暀
-     * @return 鎵归噺鎿嶄綔缁撴灉
-     */
-    BatchResult batchSend(String topic, List<String> payloads, int qos, boolean retain);
-
-    /**
-     * 鎵归噺鍙戦€佹秷鎭埌涓嶅悓涓婚
-     *
-     * @param topicPayloads 涓婚鍜屾秷鎭唴瀹圭殑鏄犲皠
-     * @return 鎵归噺鎿嶄綔缁撴灉
-     */
-    BatchResult batchSendToMultipleTopics(Map<String, String> topicPayloads);
-
-    /**
-     * 鎵归噺鍙戦€佹秷鎭埌涓嶅悓涓婚锛堟寚瀹歈oS鍜屼繚鐣欐爣蹇楋級
-     *
-     * @param topicPayloads 涓婚鍜屾秷鎭唴瀹圭殑鏄犲皠
-     * @param qos           QoS绾у埆
-     * @param retain        鏄惁淇濈暀
-     * @return 鎵归噺鎿嶄綔缁撴灉
-     */
-    BatchResult batchSendToMultipleTopics(Map<String, String> topicPayloads, int qos, boolean retain);
-
-    /**
-     * 鎵归噺鍙戦€丣SON瀵硅薄鍒板悓涓€涓婚
-     *
-     * @param topic    涓婚
-     * @param payloads 娑堟伅鍐呭瀵硅薄鍒楄〃
-     * @return 鎵归噺鎿嶄綔缁撴灉
-     */
-    BatchResult batchSendJson(String topic, List<?> payloads);
-
-    /**
-     * 鎵归噺鍙戦€丣SON瀵硅薄鍒板悓涓€涓婚锛堟寚瀹歈oS鍜屼繚鐣欐爣蹇楋級
-     *
-     * @param topic    涓婚
-     * @param payloads 娑堟伅鍐呭瀵硅薄鍒楄〃
-     * @param qos      QoS绾у埆
-     * @param retain   鏄惁淇濈暀
-     * @return 鎵归噺鎿嶄綔缁撴灉
-     */
-    BatchResult batchSendJson(String topic, List<?> payloads, int qos, boolean retain);
-
-    /**
-     * 鎵归噺鍙戦€丣SON瀵硅薄鍒颁笉鍚屼富棰?
-     *
-     * @param topicPayloads 涓婚鍜屾秷鎭唴瀹瑰璞$殑鏄犲皠
-     * @return 鎵归噺鎿嶄綔缁撴灉
-     */
-    BatchResult batchSendJsonToMultipleTopics(Map<String, Object> topicPayloads);
-
-    /**
-     * 鎵归噺鍙戦€丣SON瀵硅薄鍒颁笉鍚屼富棰橈紙鎸囧畾QoS鍜屼繚鐣欐爣蹇楋級
-     *
-     * @param topicPayloads 涓婚鍜屾秷鎭唴瀹瑰璞$殑鏄犲皠
-     * @param qos           QoS绾у埆
-     * @param retain        鏄惁淇濈暀
-     * @return 鎵归噺鎿嶄綔缁撴灉
-     */
-    BatchResult batchSendJsonToMultipleTopics(Map<String, Object> topicPayloads, int qos, boolean retain);
-
-    /**
-     * 寮傛鎵归噺鍙戦€佹秷鎭埌鍚屼竴涓婚
-     *
-     * @param topic    涓婚
-     * @param payloads 娑堟伅鍐呭鍒楄〃
-     * @return 寮傛鎿嶄綔缁撴灉
-     */
-    CompletableFuture<BatchResult> batchSendAsync(String topic, List<String> payloads);
-
-    /**
-     * 寮傛鎵归噺鍙戦€佹秷鎭埌鍚屼竴涓婚锛堟寚瀹歈oS鍜屼繚鐣欐爣蹇楋級
-     *
-     * @param topic    涓婚
-     * @param payloads 娑堟伅鍐呭鍒楄〃
-     * @param qos      QoS绾у埆
-     * @param retain   鏄惁淇濈暀
-     * @return 寮傛鎿嶄綔缁撴灉
-     */
-    CompletableFuture<BatchResult> batchSendAsync(String topic, List<String> payloads, int qos, boolean retain);
-
-    /**
-     * 鎵归噺璁㈤槄涓婚
-     *
-     * @param topics 涓婚鍒楄〃
-     * @return 鎵归噺鎿嶄綔缁撴灉
-     */
-    BatchResult batchSubscribe(List<String> topics);
-
-    /**
-     * 鎵归噺璁㈤槄涓婚锛堟寚瀹歈oS锛?
-     *
-     * @param topics 涓婚鍒楄〃
-     * @param qos    QoS绾у埆
-     * @return 鎵归噺鎿嶄綔缁撴灉
-     */
-    BatchResult batchSubscribe(List<String> topics, int qos);
-
-    /**
-     * 鎵归噺鍙栨秷璁㈤槄涓婚
-     *
-     * @param topics 涓婚鍒楄〃
-     * @return 鎵归噺鎿嶄綔缁撴灉
-     */
-    BatchResult batchUnsubscribe(List<String> topics);
-
-    /**
-     * 浣跨敤鍚堝苟绛栫暐鍙戦€佹秷鎭?
-     * 灏嗗涓皬娑堟伅鍚堝苟涓轰竴涓ぇ娑堟伅鍙戦€侊紝浠ュ噺灏戠綉缁滃紑閿€
-     *
-     * @param topic    涓婚
-     * @param payloads 娑堟伅鍐呭鍒楄〃
-     * @param strategy 鍚堝苟绛栫暐
-     * @return 鎵归噺鎿嶄綔缁撴灉
-     */
-    BatchResult sendWithMergeStrategy(String topic, List<String> payloads, MergeStrategy strategy);
-
-    /**
-     * 浣跨敤鍒嗙墖绛栫暐鍙戦€佸ぇ娑堟伅
-     * 灏嗕竴涓ぇ娑堟伅鍒嗗壊涓哄涓皬娑堟伅鍙戦€侊紝浠ラ伩鍏嶈秴杩嘙QTT娑堟伅澶у皬闄愬埗
-     *
-     * @param topic   涓婚
-     * @param payload 澶ф秷鎭唴瀹?
-     * @param strategy 鍒嗙墖绛栫暐
-     * @return 鎵归噺鎿嶄綔缁撴灉
-     */
-    BatchResult sendWithSplitStrategy(String topic, String payload, SplitStrategy strategy);
-} 
-
-

+ 0 - 41
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/SplitStrategy.java

@@ -1,41 +0,0 @@
-package cn.hfln.framework.mqtt.batch;
-
-import java.util.List;
-
-/**
- * 娑堟伅鍒嗙墖绛栫暐鎺ュ彛
- * 鐢ㄤ簬灏嗕竴涓ぇ娑堟伅鍒嗗壊涓哄涓皬娑堟伅锛屼互閬垮厤瓒呰繃MQTT娑堟伅澶у皬闄愬埗
- */
-public interface SplitStrategy {
-
-    /**
-     * 灏嗕竴涓ぇ娑堟伅鍒嗗壊涓哄涓皬娑堟伅
-     *
-     * @param payload 寰呭垎鍓茬殑澶ф秷鎭?
-     * @return 鍒嗗壊鍚庣殑灏忔秷鎭垪琛?
-     */
-    List<String> split(String payload);
-
-    /**
-     * 鑾峰彇鍒嗙墖绛栫暐鐨勫悕绉?
-     *
-     * @return 绛栫暐鍚嶇О
-     */
-    String getName();
-
-    /**
-     * 鑾峰彇鍒嗙墖绛栫暐鐨勬弿杩?
-     *
-     * @return 绛栫暐鎻忚堪
-     */
-    String getDescription();
-
-    /**
-     * 鑾峰彇鍒嗙墖澶у皬闄愬埗锛堝瓧鑺傦級
-     *
-     * @return 鍒嗙墖澶у皬闄愬埗
-     */
-    int getMaxPayloadSize();
-} 
-
-

+ 0 - 0
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/config/MqttBatchAutoConfiguration.java


+ 0 - 107
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/impl/DelimiterMergeStrategy.java

@@ -1,107 +0,0 @@
-package cn.hfln.framework.mqtt.batch.impl;
-
-import cn.hfln.framework.mqtt.batch.MergeStrategy;
-
-import java.util.List;
-
-/**
- * 鍒嗛殧绗﹀悎骞剁瓥鐣?
- * 浣跨敤鎸囧畾鐨勫垎闅旂灏嗗涓秷鎭悎骞朵负涓€涓?
- */
-public class DelimiterMergeStrategy implements MergeStrategy {
-
-    private final String delimiter;
-    private final String name;
-    private final String description;
-
-    /**
-     * 鍒涘缓涓€涓垎闅旂鍚堝苟绛栫暐
-     *
-     * @param delimiter 鍒嗛殧绗?
-     */
-    public DelimiterMergeStrategy(String delimiter) {
-        this(delimiter, "DelimiterMerge", "使用分隔符[" + delimiter + "]合并消息");
-    }
-
-    /**
-     * 鍒涘缓涓€涓垎闅旂鍚堝苟绛栫暐
-     *
-     * @param delimiter   鍒嗛殧绗?
-     * @param name        绛栫暐鍚嶇О
-     * @param description 绛栫暐鎻忚堪
-     */
-    public DelimiterMergeStrategy(String delimiter, String name, String description) {
-        this.delimiter = delimiter;
-        this.name = name;
-        this.description = description;
-    }
-
-    @Override
-    public String merge(List<String> payloads) {
-        if (payloads == null || payloads.isEmpty()) {
-            return "";
-        }
-
-        StringBuilder result = new StringBuilder();
-        boolean first = true;
-
-        for (String payload : payloads) {
-            if (first) {
-                first = false;
-            } else {
-                result.append(delimiter);
-            }
-            result.append(payload);
-        }
-
-        return result.toString();
-    }
-
-    @Override
-    public String getName() {
-        return name;
-    }
-
-    @Override
-    public String getDescription() {
-        return description;
-    }
-
-    /**
-     * 鑾峰彇鍒嗛殧绗?
-     *
-     * @return 鍒嗛殧绗?
-     */
-    public String getDelimiter() {
-        return delimiter;
-    }
-
-    /**
-     * 鍒涘缓涓€涓娇鐢ㄦ崲琛岀鍚堝苟鐨勭瓥鐣?
-     *
-     * @return 鎹㈣绗﹀悎骞剁瓥鐣?
-     */
-    public static DelimiterMergeStrategy newLine() {
-        return new DelimiterMergeStrategy("\n", "NewLineMerge", "使用换行符合并消息");
-    }
-
-    /**
-     * 鍒涘缓涓€涓娇鐢ㄩ€楀彿鍚堝苟鐨勭瓥鐣?
-     *
-     * @return 閫楀彿鍚堝苟绛栫暐
-     */
-    public static DelimiterMergeStrategy comma() {
-        return new DelimiterMergeStrategy(",", "CommaMerge", "使用逗号合并消息");
-    }
-
-    /**
-     * 鍒涘缓涓€涓娇鐢ㄥ垎鍙峰悎骞剁殑绛栫暐
-     *
-     * @return 鍒嗗彿鍚堝苟绛栫暐
-     */
-    public static DelimiterMergeStrategy semicolon() {
-        return new DelimiterMergeStrategy(";", "SemicolonMerge", "使用分号合并消息");
-    }
-} 
-
-

+ 0 - 57
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/impl/JsonArrayMergeStrategy.java

@@ -1,57 +0,0 @@
-package cn.hfln.framework.mqtt.batch.impl;
-
-import cn.hfln.framework.mqtt.batch.MergeStrategy;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import java.util.List;
-
-/**
- * JSON鏁扮粍鍚堝苟绛栫暐
- * 灏嗗涓狫SON瀵硅薄鍚堝苟涓轰竴涓狫SON鏁扮粍
- */
-public class JsonArrayMergeStrategy implements MergeStrategy {
-
-    private final ObjectMapper objectMapper;
-
-    public JsonArrayMergeStrategy() {
-        this.objectMapper = new ObjectMapper();
-    }
-
-    public JsonArrayMergeStrategy(ObjectMapper objectMapper) {
-        this.objectMapper = objectMapper;
-    }
-
-    @Override
-    public String merge(List<String> payloads) {
-        try {
-            // 灏嗘瘡涓狫SON瀛楃涓茶В鏋愪负瀵硅薄锛岀劧鍚庡悎骞跺埌涓€涓暟缁勪腑
-            Object[] jsonObjects = payloads.stream()
-                    .map(payload -> {
-                        try {
-                            return objectMapper.readValue(payload, Object.class);
-                        } catch (Exception e) {
-                            // 濡傛灉瑙f瀽澶辫触锛屽垯浣跨敤鍘熷瀛楃涓?
-                            return payload;
-                        }
-                    })
-                    .toArray();
-
-            // 灏嗘暟缁勫簭鍒楀寲涓篔SON瀛楃涓?
-            return objectMapper.writeValueAsString(jsonObjects);
-        } catch (Exception e) {
-            throw new RuntimeException("Failed to merge JSON payloads: " + e.getMessage(), e);
-        }
-    }
-
-    @Override
-    public String getName() {
-        return "JsonArrayMerge";
-    }
-
-    @Override
-    public String getDescription() {
-        return "灏嗗涓狫SON瀵硅薄鍚堝苟涓轰竴涓狫SON鏁扮粍";
-    }
-} 
-
-

+ 0 - 180
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/impl/JsonSplitStrategy.java

@@ -1,180 +0,0 @@
-package cn.hfln.framework.mqtt.batch.impl;
-
-import cn.hfln.framework.mqtt.batch.SplitStrategy;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * JSON鍒嗙墖绛栫暐
- * 鎸夌収JSON缁撴瀯鍒嗗壊娑堟伅锛岄€傜敤浜嶫SON鏁扮粍鎴栧寘鍚暟缁勫瓧娈电殑JSON瀵硅薄
- */
-public class JsonSplitStrategy implements SplitStrategy {
-
-    private final ObjectMapper objectMapper;
-    private final int maxItemsPerChunk;
-    private final String arrayField;
-    private final int maxPayloadSize;
-
-    /**
-     * 鍒涘缓涓€涓狫SON鍒嗙墖绛栫暐锛岀敤浜庡鐞咼SON鏁扮粍
-     *
-     * @param maxItemsPerChunk 姣忎釜鍒嗙墖鐨勬渶澶ч」鐩暟
-     */
-    public JsonSplitStrategy(int maxItemsPerChunk) {
-        this(maxItemsPerChunk, null, SizeLimitSplitStrategy.DEFAULT_MAX_PAYLOAD_SIZE);
-    }
-
-    /**
-     * 鍒涘缓涓€涓狫SON鍒嗙墖绛栫暐锛岀敤浜庡鐞嗗寘鍚暟缁勫瓧娈电殑JSON瀵硅薄
-     *
-     * @param maxItemsPerChunk 姣忎釜鍒嗙墖鐨勬渶澶ч」鐩暟
-     * @param arrayField       瑕佸垎鍓茬殑鏁扮粍瀛楁鍚?
-     */
-    public JsonSplitStrategy(int maxItemsPerChunk, String arrayField) {
-        this(maxItemsPerChunk, arrayField, SizeLimitSplitStrategy.DEFAULT_MAX_PAYLOAD_SIZE);
-    }
-
-    /**
-     * 鍒涘缓涓€涓狫SON鍒嗙墖绛栫暐
-     *
-     * @param maxItemsPerChunk 姣忎釜鍒嗙墖鐨勬渶澶ч」鐩暟
-     * @param arrayField       瑕佸垎鍓茬殑鏁扮粍瀛楁鍚嶏紝濡傛灉涓簄ull鍒欒〃绀烘暣涓狫SON鏄竴涓暟缁?
-     * @param maxPayloadSize   鏈€澶ф秷鎭ぇ灏忥紙瀛楄妭锛?
-     */
-    public JsonSplitStrategy(int maxItemsPerChunk, String arrayField, int maxPayloadSize) {
-        if (maxItemsPerChunk <= 0) {
-            throw new IllegalArgumentException("Max items per chunk must be positive");
-        }
-        if (maxPayloadSize <= 0) {
-            throw new IllegalArgumentException("Max payload size must be positive");
-        }
-        this.maxItemsPerChunk = maxItemsPerChunk;
-        this.arrayField = arrayField;
-        this.maxPayloadSize = maxPayloadSize;
-        this.objectMapper = new ObjectMapper();
-    }
-
-    @Override
-    public List<String> split(String payload) {
-        if (payload == null || payload.isEmpty()) {
-            return Collections.emptyList();
-        }
-
-        try {
-            JsonNode rootNode = objectMapper.readTree(payload);
-            
-            // 纭畾瑕佸垎鍓茬殑鏁扮粍鑺傜偣
-            ArrayNode arrayNode;
-            ObjectNode template = null;
-            
-            if (arrayField == null) {
-                // 鏁翠釜JSON鏄竴涓暟缁?
-                if (!rootNode.isArray()) {
-                    // 濡傛灉涓嶆槸鏁扮粍锛屽垯鏃犳硶鍒嗗壊锛岀洿鎺ヨ繑鍥炲師濮嬫秷鎭?
-                    return Collections.singletonList(payload);
-                }
-                arrayNode = (ArrayNode) rootNode;
-            } else {
-                // JSON瀵硅薄涓殑鐗瑰畾鏁扮粍瀛楁
-                if (!rootNode.isObject() || !rootNode.has(arrayField) || !rootNode.get(arrayField).isArray()) {
-                    // 濡傛灉涓嶆槸瀵硅薄锛屾垨鑰呮病鏈夋寚瀹氱殑鏁扮粍瀛楁锛屽垯鏃犳硶鍒嗗壊锛岀洿鎺ヨ繑鍥炲師濮嬫秷鎭?
-                    return Collections.singletonList(payload);
-                }
-                
-                // 淇濆瓨瀵硅薄妯℃澘锛岀敤浜庡悗缁垱寤哄垎鐗?
-                template = (ObjectNode) rootNode.deepCopy();
-                arrayNode = (ArrayNode) rootNode.get(arrayField);
-                template.remove(arrayField);
-            }
-            
-            // 濡傛灉鏁扮粍涓虹┖鎴栬€呭彧鏈変竴涓厓绱狅紝鍒欐棤闇€鍒嗗壊
-            if (arrayNode.size() <= maxItemsPerChunk) {
-                return Collections.singletonList(payload);
-            }
-            
-            // 鍒嗗壊鏁扮粍
-            List<String> chunks = new ArrayList<>();
-            int totalItems = arrayNode.size();
-            int chunkCount = (totalItems + maxItemsPerChunk - 1) / maxItemsPerChunk; // 鍚戜笂鍙栨暣
-            
-            for (int i = 0; i < chunkCount; i++) {
-                int startIdx = i * maxItemsPerChunk;
-                int endIdx = Math.min((i + 1) * maxItemsPerChunk, totalItems);
-                
-                // 鍒涘缓鍒嗙墖
-                if (arrayField == null) {
-                    // 鏁翠釜JSON鏄竴涓暟缁?
-                    ArrayNode chunkArray = objectMapper.createArrayNode();
-                    for (int j = startIdx; j < endIdx; j++) {
-                        chunkArray.add(arrayNode.get(j));
-                    }
-                    chunks.add(objectMapper.writeValueAsString(chunkArray));
-                } else {
-                    // JSON瀵硅薄涓殑鐗瑰畾鏁扮粍瀛楁
-                    ObjectNode chunkObj = template.deepCopy();
-                    ArrayNode chunkArray = objectMapper.createArrayNode();
-                    for (int j = startIdx; j < endIdx; j++) {
-                        chunkArray.add(arrayNode.get(j));
-                    }
-                    chunkObj.set(arrayField, chunkArray);
-                    chunks.add(objectMapper.writeValueAsString(chunkObj));
-                }
-            }
-            
-            return chunks;
-            
-        } catch (Exception e) {
-            // 濡傛灉瑙f瀽澶辫触锛屽垯浣跨敤澶у皬闄愬埗鍒嗙墖绛栫暐浣滀负鍚庡
-            SizeLimitSplitStrategy backupStrategy = new SizeLimitSplitStrategy(maxPayloadSize);
-            return backupStrategy.split(payload);
-        }
-    }
-
-    @Override
-    public String getName() {
-        return "JsonSplit";
-    }
-
-    @Override
-    public String getDescription() {
-        if (arrayField == null) {
-            // 按照 JSON 数组结构分割消息,每个分片最多包含 maxItemsPerChunk 个元素
-            return "按照JSON数组结构分割消息,每个分片最多包含" + maxItemsPerChunk + "个元素";
-        } else {
-            // 按照 JSON 对象中的 arrayField 数组字段分割消息,每个分片最多包含 maxItemsPerChunk 个元素
-            return "按照JSON对象中的" + arrayField + "数组字段分割消息,每个分片最多包含" + maxItemsPerChunk + "个元素";
-        }
-    }
-
-    @Override
-    public int getMaxPayloadSize() {
-        return maxPayloadSize;
-    }
-
-    /**
-     * 鑾峰彇姣忎釜鍒嗙墖鐨勬渶澶ч」鐩暟
-     *
-     * @return 姣忎釜鍒嗙墖鐨勬渶澶ч」鐩暟
-     */
-    public int getMaxItemsPerChunk() {
-        return maxItemsPerChunk;
-    }
-
-    /**
-     * 鑾峰彇瑕佸垎鍓茬殑鏁扮粍瀛楁鍚?
-     *
-     * @return 鏁扮粍瀛楁鍚嶏紝濡傛灉涓簄ull鍒欒〃绀烘暣涓狫SON鏄竴涓暟缁?
-     */
-    public String getArrayField() {
-        return arrayField;
-    }
-} 
-
-

+ 0 - 142
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/impl/MqttBatchTemplate.java

@@ -1,142 +0,0 @@
-package cn.hfln.framework.mqtt.batch.impl;
-
-import cn.hfln.framework.mqtt.batch.*;
-import java.util.*;
-import java.util.concurrent.CompletableFuture;
-
-/**
- * MqttBatchOperations基础实现,支持批量发送、订阅、合并、分片等主流程。
- */
-public class MqttBatchTemplate implements MqttBatchOperations {
-    @Override
-    public BatchResult batchSend(String topic, List<String> payloads) {
-        return batchSend(topic, payloads, 1, false);
-    }
-
-    @Override
-    public BatchResult batchSend(String topic, List<String> payloads, int qos, boolean retain) {
-        BatchResult result = new BatchResult();
-        for (String payload : payloads) {
-            try {
-                // 假设全部成功
-                result.addResult(BatchResult.success(topic, payload));
-            } catch (Exception e) {
-                result.addResult(BatchResult.failure(topic, payload, e.getMessage(), e));
-            }
-        }
-        return result;
-    }
-
-    @Override
-    public BatchResult batchSendToMultipleTopics(Map<String, String> topicPayloads) {
-        return batchSendToMultipleTopics(topicPayloads, 1, false);
-    }
-
-    @Override
-    public BatchResult batchSendToMultipleTopics(Map<String, String> topicPayloads, int qos, boolean retain) {
-        BatchResult result = new BatchResult();
-        for (Map.Entry<String, String> entry : topicPayloads.entrySet()) {
-            try {
-                result.addResult(BatchResult.success(entry.getKey(), entry.getValue()));
-            } catch (Exception e) {
-                result.addResult(BatchResult.failure(entry.getKey(), entry.getValue(), e.getMessage(), e));
-            }
-        }
-        return result;
-    }
-
-    @Override
-    public BatchResult batchSendJson(String topic, List<?> payloads) {
-        return batchSendJson(topic, payloads, 1, false);
-    }
-
-    @Override
-    public BatchResult batchSendJson(String topic, List<?> payloads, int qos, boolean retain) {
-        BatchResult result = new BatchResult();
-        for (Object payload : payloads) {
-            try {
-                result.addResult(BatchResult.success(topic, String.valueOf(payload)));
-            } catch (Exception e) {
-                result.addResult(BatchResult.failure(topic, String.valueOf(payload), e.getMessage(), e));
-            }
-        }
-        return result;
-    }
-
-    @Override
-    public BatchResult batchSendJsonToMultipleTopics(Map<String, Object> topicPayloads) {
-        return batchSendJsonToMultipleTopics(topicPayloads, 1, false);
-    }
-
-    @Override
-    public BatchResult batchSendJsonToMultipleTopics(Map<String, Object> topicPayloads, int qos, boolean retain) {
-        BatchResult result = new BatchResult();
-        for (Map.Entry<String, Object> entry : topicPayloads.entrySet()) {
-            try {
-                result.addResult(BatchResult.success(entry.getKey(), String.valueOf(entry.getValue())));
-            } catch (Exception e) {
-                result.addResult(BatchResult.failure(entry.getKey(), String.valueOf(entry.getValue()), e.getMessage(), e));
-            }
-        }
-        return result;
-    }
-
-    @Override
-    public CompletableFuture<BatchResult> batchSendAsync(String topic, List<String> payloads) {
-        return CompletableFuture.supplyAsync(() -> batchSend(topic, payloads));
-    }
-
-    @Override
-    public CompletableFuture<BatchResult> batchSendAsync(String topic, List<String> payloads, int qos, boolean retain) {
-        return CompletableFuture.supplyAsync(() -> batchSend(topic, payloads, qos, retain));
-    }
-
-    @Override
-    public BatchResult batchSubscribe(List<String> topics) {
-        return batchSubscribe(topics, 1);
-    }
-
-    @Override
-    public BatchResult batchSubscribe(List<String> topics, int qos) {
-        BatchResult result = new BatchResult();
-        for (String topic : topics) {
-            try {
-                result.addResult(BatchResult.success(topic, null));
-            } catch (Exception e) {
-                result.addResult(BatchResult.failure(topic, null, e.getMessage(), e));
-            }
-        }
-        return result;
-    }
-
-    @Override
-    public BatchResult batchUnsubscribe(List<String> topics) {
-        BatchResult result = new BatchResult();
-        for (String topic : topics) {
-            try {
-                result.addResult(BatchResult.success(topic, null));
-            } catch (Exception e) {
-                result.addResult(BatchResult.failure(topic, null, e.getMessage(), e));
-            }
-        }
-        return result;
-    }
-
-    @Override
-    public BatchResult sendWithMergeStrategy(String topic, List<String> payloads, MergeStrategy strategy) {
-        String merged = strategy.merge(payloads);
-        BatchResult result = new BatchResult();
-        try {
-            result.addResult(BatchResult.success(topic, merged));
-        } catch (Exception e) {
-            result.addResult(BatchResult.failure(topic, merged, e.getMessage(), e));
-        }
-        return result;
-    }
-
-    @Override
-    public BatchResult sendWithSplitStrategy(String topic, String payload, SplitStrategy strategy) {
-        List<String> parts = strategy.split(payload);
-        return batchSend(topic, parts);
-    }
-}

+ 0 - 148
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/batch/impl/SizeLimitSplitStrategy.java

@@ -1,148 +0,0 @@
-package cn.hfln.framework.mqtt.batch.impl;
-
-import cn.hfln.framework.mqtt.batch.SplitStrategy;
-
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * 澶у皬闄愬埗鍒嗙墖绛栫暐
- * 鎸夌収鎸囧畾鐨勫ぇ灏忛檺鍒跺皢澶ф秷鎭垎鍓蹭负澶氫釜灏忔秷鎭?
- */
-public class SizeLimitSplitStrategy implements SplitStrategy {
-
-    /**
-     * MQTT鍗忚榛樿鏈€澶ф秷鎭ぇ灏忥紙256KB锛?
-     */
-    public static final int DEFAULT_MAX_PAYLOAD_SIZE = 256 * 1024;
-
-    private final int maxPayloadSize;
-    private final String name;
-    private final String description;
-
-    /**
-     * 鍒涘缓涓€涓ぇ灏忛檺鍒跺垎鐗囩瓥鐣ワ紝浣跨敤榛樿鐨勬渶澶ф秷鎭ぇ灏忥紙256KB锛?
-     */
-    public SizeLimitSplitStrategy() {
-        this(DEFAULT_MAX_PAYLOAD_SIZE);
-    }
-
-    /**
-     * 鍒涘缓涓€涓ぇ灏忛檺鍒跺垎鐗囩瓥鐣?
-     *
-     * @param maxPayloadSize 鏈€澶ф秷鎭ぇ灏忥紙瀛楄妭锛?
-     */
-    public SizeLimitSplitStrategy(int maxPayloadSize) {
-        this(maxPayloadSize, "SizeLimitSplit", "鎸夌収澶у皬闄愬埗" + maxPayloadSize + "瀛楄妭鍒嗗壊娑堟伅");
-    }
-
-    /**
-     * 鍒涘缓涓€涓ぇ灏忛檺鍒跺垎鐗囩瓥鐣?
-     *
-     * @param maxPayloadSize 鏈€澶ф秷鎭ぇ灏忥紙瀛楄妭锛?
-     * @param name           绛栫暐鍚嶇О
-     * @param description    绛栫暐鎻忚堪
-     */
-    public SizeLimitSplitStrategy(int maxPayloadSize, String name, String description) {
-        if (maxPayloadSize <= 0) {
-            throw new IllegalArgumentException("Max payload size must be positive");
-        }
-        this.maxPayloadSize = maxPayloadSize;
-        this.name = name;
-        this.description = description;
-    }
-
-    @Override
-    public List<String> split(String payload) {
-        if (payload == null || payload.isEmpty()) {
-            return Collections.emptyList();
-        }
-
-        List<String> chunks = new ArrayList<>();
-        byte[] bytes = payload.getBytes(StandardCharsets.UTF_8);
-        int totalLength = bytes.length;
-
-        // 濡傛灉娑堟伅澶у皬灏忎簬鏈€澶ч檺鍒讹紝鍒欑洿鎺ヨ繑鍥?
-        if (totalLength <= maxPayloadSize) {
-            chunks.add(payload);
-            return chunks;
-        }
-
-        int offset = 0;
-        while (offset < totalLength) {
-            int chunkSize = Math.min(maxPayloadSize, totalLength - offset);
-            
-            // 璁$畻瀹為檯鐨勫垎鐗囩粨鏉熶綅缃紝纭繚涓嶄細鍒囧壊UTF-8瀛楃
-            int endPos = calculateSafeUtf8End(bytes, offset, chunkSize);
-            
-            // 鍒涘缓鍒嗙墖
-            String chunk = new String(bytes, offset, endPos - offset, StandardCharsets.UTF_8);
-            chunks.add(chunk);
-            
-            // 鏇存柊鍋忕Щ閲?
-            offset = endPos;
-        }
-
-        return chunks;
-    }
-
-    /**
-     * 璁$畻UTF-8瀹夊叏鐨勭粨鏉熶綅缃紝纭繚涓嶄細鍒囧壊UTF-8瀛楃
-     *
-     * @param bytes     瀛楄妭鏁扮粍
-     * @param offset    璧峰鍋忕Щ閲?
-     * @param chunkSize 鍒嗙墖澶у皬
-     * @return 瀹夊叏鐨勭粨鏉熶綅缃?
-     */
-    private int calculateSafeUtf8End(byte[] bytes, int offset, int chunkSize) {
-        int end = offset + chunkSize;
-        if (end >= bytes.length) {
-            return bytes.length;
-        }
-
-        // 妫€鏌ョ粨鏉熶綅缃槸鍚﹀湪UTF-8瀛楃鐨勪腑闂?
-        // UTF-8瀛楃鐨勭涓€涓瓧鑺傜殑鏈€楂樹綅鏄?锛屾垨鑰呮槸110x xxxx, 1110 xxxx, 1111 0xxx
-        // 鑰屽悗缁瓧鑺傜殑鏍煎紡鏄?0xx xxxx
-        // 濡傛灉缁撴潫浣嶇疆鐨勫瓧鑺傛槸10xx xxxx锛屽垯璇存槑瀹冩槸UTF-8瀛楃鐨勪腑闂村瓧鑺?
-        int pos = end - 1;
-        while (pos > offset && (bytes[pos] & 0xC0) == 0x80) {
-            pos--;
-        }
-
-        // 璁$畻褰撳墠UTF-8瀛楃鐨勯暱搴?
-        int charLen = 1;
-        if ((bytes[pos] & 0xE0) == 0xC0) { // 110x xxxx锛?瀛楄妭瀛楃
-            charLen = 2;
-        } else if ((bytes[pos] & 0xF0) == 0xE0) { // 1110 xxxx锛?瀛楄妭瀛楃
-            charLen = 3;
-        } else if ((bytes[pos] & 0xF8) == 0xF0) { // 1111 0xxx锛?瀛楄妭瀛楃
-            charLen = 4;
-        }
-
-        // 濡傛灉瀛楃闀垮害瓒呰繃浜嗙粨鏉熶綅缃紝鍒欓渶瑕佸洖閫€
-        if (pos + charLen > end) {
-            return pos;
-        }
-
-        return end;
-    }
-
-    @Override
-    public String getName() {
-        return name;
-    }
-
-    @Override
-    public String getDescription() {
-        return description;
-    }
-
-    @Override
-    public int getMaxPayloadSize() {
-        return maxPayloadSize;
-    }
-} 
-
-

+ 0 - 256
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/config/MqttAutoConfiguration.java

@@ -1,256 +0,0 @@
-package cn.hfln.framework.mqtt.config;
-
-import cn.hfln.framework.mqtt.converter.JsonMessageConverter;
-import cn.hfln.framework.mqtt.converter.MessageConverter;
-import cn.hfln.framework.mqtt.gateway.DefaultMqttGateway;
-import cn.hfln.framework.mqtt.gateway.MqttGateway;
-import cn.hfln.framework.mqtt.handler.MqttSubscriberProcessor;
-import cn.hfln.framework.mqtt.interceptor.MqttMessageInterceptor;
-import cn.hfln.framework.mqtt.listener.MqttConnectionListener;
-import cn.hfln.framework.mqtt.listener.MqttMessageListener;
-import cn.hfln.framework.mqtt.template.MqttTemplate;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.paho.client.mqttv3.MqttClient;
-import org.eclipse.paho.client.mqttv3.MqttClientPersistence;
-import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
-import org.eclipse.paho.client.mqttv3.MqttException;
-import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.integration.channel.DirectChannel;
-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 java.util.Collections;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * MQTT自动配置类
- */
-@Slf4j
-@Configuration
-@EnableConfigurationProperties(MqttProperties.class)
-@ConditionalOnProperty(prefix = "mqtt", name = "enabled", havingValue = "true", matchIfMissing = true)
-public class MqttAutoConfiguration {
-
-    private final MqttProperties mqttProperties;
-
-    @Autowired
-    public MqttAutoConfiguration(MqttProperties mqttProperties) {
-        this.mqttProperties = mqttProperties;
-    }
-
-    @Bean
-    @ConditionalOnMissingBean
-    public MessageConverter messageConverter() {
-        return new JsonMessageConverter();
-    }
-
-    @Bean
-    @ConditionalOnMissingBean
-    public MqttClientPersistence mqttClientPersistence() {
-        return new MemoryPersistence();
-    }
-
-    @Bean
-    @ConditionalOnMissingBean
-    public MqttConnectOptions mqttConnectOptions() {
-        MqttConnectOptions options = new MqttConnectOptions();
-        options.setServerURIs(new String[]{mqttProperties.getBroker()});
-        options.setUserName(mqttProperties.getUsername());
-        options.setPassword(mqttProperties.getPassword().toCharArray());
-        options.setKeepAliveInterval(mqttProperties.getKeepalive());
-        options.setConnectionTimeout(mqttProperties.getTimeout());
-        options.setCleanSession(mqttProperties.isCleanSession());
-        options.setAutomaticReconnect(mqttProperties.isAutomaticReconnect());
-        return options;
-    }
-
-    @Bean
-    @ConditionalOnMissingBean
-    public MqttPahoClientFactory mqttClientFactory(MqttConnectOptions mqttConnectOptions) {
-        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
-        factory.setConnectionOptions(mqttConnectOptions);
-        return factory;
-    }
-
-    @Bean
-    @ConditionalOnMissingBean
-    public MqttClient mqttClient(MqttClientPersistence mqttClientPersistence) throws MqttException {
-        String clientId = mqttProperties.getClientId();
-        if (clientId == null || clientId.isEmpty()) {
-            clientId = "mqtt-client-" + UUID.randomUUID();
-        }
-        
-        MqttClient mqttClient = new MqttClient(mqttProperties.getBroker(), clientId, mqttClientPersistence);
-        
-        // 设置回调
-        mqttClient.setCallback(new MqttClientCallback(mqttClient, mqttConnectionListeners()));
-        
-        // 连接MQTT服务器
-        try {
-            MqttConnectOptions options = mqttConnectOptions();
-            mqttClient.connect(options);
-            log.info("Connected to MQTT broker: {}", mqttProperties.getBroker());
-        } catch (MqttException e) {
-            log.error("Failed to connect to MQTT broker: {}", mqttProperties.getBroker(), e);
-            // 后台尝试重连
-            if (mqttProperties.isAutomaticReconnect()) {
-                new Thread(() -> {
-                    int retryCount = 0;
-                    while (!mqttClient.isConnected() && retryCount < mqttProperties.getMaxReconnectAttempts()) {
-                        try {
-                            Thread.sleep(mqttProperties.getReconnectInterval());
-                            mqttClient.connect(mqttConnectOptions());
-                            log.info("Successfully reconnected to MQTT broker");
-                            break;
-                        } catch (Exception ex) {
-                            retryCount++;
-                            log.error("Failed to reconnect to MQTT broker, attempt: {}", retryCount, ex);
-                        }
-                    }
-                }).start();
-            }
-        }
-        
-        return mqttClient;
-    }
-
-    @Bean
-    @ConditionalOnMissingBean
-    public MqttTemplate mqttTemplate(MqttClient mqttClient, 
-                                    MessageConverter messageConverter) {
-        List<MqttMessageInterceptor> interceptors = mqttMessageInterceptors();
-        return new MqttTemplate(mqttClient, interceptors, messageConverter);
-    }
-    
-    @Bean
-    @ConditionalOnMissingBean
-    public MqttGateway mqttGateway(MqttTemplate mqttTemplate, MqttClient mqttClient) {
-        return new DefaultMqttGateway(mqttTemplate, mqttClient);
-    }
-
-    @Bean
-    @ConditionalOnMissingBean
-    public List<MqttMessageInterceptor> mqttMessageInterceptors() {
-        return Collections.emptyList();
-    }
-
-    @Bean
-    @ConditionalOnMissingBean
-    public List<MqttConnectionListener> mqttConnectionListeners() {
-        return Collections.emptyList();
-    }
-
-    @Bean
-    @ConditionalOnMissingBean
-    public List<MqttMessageListener> mqttMessageListeners() {
-        return Collections.emptyList();
-    }
-
-    @Bean
-    @ConditionalOnMissingBean
-    public MessageChannel mqttInputChannel() {
-        return new DirectChannel();
-    }
-
-    @Bean
-    @ConditionalOnMissingBean
-    public MqttPahoMessageHandler mqttOutbound(MqttPahoClientFactory mqttClientFactory) {
-        String clientId = mqttProperties.getClientId();
-        if (clientId == null || clientId.isEmpty()) {
-            clientId = "mqtt-outbound-" + UUID.randomUUID();
-        }
-        
-        MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(clientId + "-outbound", mqttClientFactory);
-        messageHandler.setDefaultQos(mqttProperties.getDefaultQos());
-        messageHandler.setDefaultRetained(mqttProperties.isDefaultRetained());
-        messageHandler.setAsync(mqttProperties.isAsync());
-        return messageHandler;
-    }
-
-    @Bean
-    @ConditionalOnMissingBean
-    public MqttPahoMessageDrivenChannelAdapter mqttInbound(MqttPahoClientFactory mqttClientFactory) {
-        String clientId = mqttProperties.getClientId();
-        if (clientId == null || clientId.isEmpty()) {
-            clientId = "mqtt-inbound-" + UUID.randomUUID();
-        }
-        
-        MqttPahoMessageDrivenChannelAdapter adapter = 
-                new MqttPahoMessageDrivenChannelAdapter(clientId + "-inbound", mqttClientFactory);
-        
-        // 设置消息转换器
-        DefaultPahoMessageConverter converter = new DefaultPahoMessageConverter();
-        converter.setPayloadAsBytes(false);
-        adapter.setConverter(converter);
-        
-        // 设置通道
-        adapter.setOutputChannel(mqttInputChannel());
-        
-        // 设置QoS
-        adapter.setQos(mqttProperties.getDefaultQos());
-        
-        return adapter;
-    }
-    
-    @Bean
-    @ConditionalOnMissingBean
-    public MqttSubscriberProcessor mqttSubscriberProcessor(MqttPahoMessageDrivenChannelAdapter mqttInbound,
-                                                        MqttClient mqttClient) {
-        return new MqttSubscriberProcessor(mqttInbound, mqttClient);
-    }
-    
-    /**
-     * MQTT客户端回调类
-     */
-    private static class MqttClientCallback implements org.eclipse.paho.client.mqttv3.MqttCallback {
-        private final MqttClient mqttClient;
-        private final List<MqttConnectionListener> connectionListeners;
-        
-        public MqttClientCallback(MqttClient mqttClient, List<MqttConnectionListener> connectionListeners) {
-            this.mqttClient = mqttClient;
-            this.connectionListeners = connectionListeners;
-        }
-        
-        @Override
-        public void connectionLost(Throwable cause) {
-            log.warn("MQTT connection lost: {}", cause.getMessage());
-            
-            // 通知连接监听器
-            for (MqttConnectionListener listener : connectionListeners) {
-                try {
-                    listener.connectionLost(cause);
-                } catch (Exception e) {
-                    log.error("Error notifying connection listener", e);
-                }
-            }
-        }
-        
-        @Override
-        public void messageArrived(String topic, org.eclipse.paho.client.mqttv3.MqttMessage message) {
-            // 消息由MqttPahoMessageDrivenChannelAdapter处理
-        }
-        
-        @Override
-        public void deliveryComplete(org.eclipse.paho.client.mqttv3.IMqttDeliveryToken token) {
-            // 通知连接监听器
-            for (MqttConnectionListener listener : connectionListeners) {
-                try {
-                    listener.deliveryComplete(token);
-                } catch (Exception e) {
-                    log.error("Error notifying delivery complete listener", e);
-                }
-            }
-        }
-    }
-} 

+ 0 - 49
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/config/MqttClientConfig.java

@@ -1,49 +0,0 @@
-package cn.hfln.framework.mqtt.config;
-
-import cn.hfln.framework.mqtt.handler.MqttMessageHandler;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.paho.client.mqttv3.MqttClient;
-import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
-import org.eclipse.paho.client.mqttv3.MqttException;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Lazy;
-
-@Slf4j
-@Configuration
-@EnableConfigurationProperties(MqttProperties.class)
-@ComponentScan("cn.hfln.framework.mqtt")
-public class MqttClientConfig {
-
-    @Autowired
-    private MqttProperties mqttProperties;
-
-    @Bean
-    @ConditionalOnMissingBean
-    public MqttConnectOptions mqttConnectOptions() {
-        MqttConnectOptions options = new MqttConnectOptions();
-        options.setServerURIs(new String[]{mqttProperties.getBroker()});
-        options.setUserName(mqttProperties.getUsername());
-        options.setPassword(mqttProperties.getPassword().toCharArray());
-        options.setConnectionTimeout(mqttProperties.getConnectionTimeout());
-        options.setKeepAliveInterval(mqttProperties.getKeepalive());
-        options.setAutomaticReconnect(mqttProperties.isAutomaticReconnect());
-        options.setCleanSession(mqttProperties.isCleanSession());
-        return options;
-    }
-
-    @Bean
-    @ConditionalOnMissingBean
-    public MqttClient mqttClient(MqttConnectOptions options, @Lazy MqttMessageHandler mqttMessageHandler) throws MqttException {
-        log.info("Creating MQTT client with client ID: {}", mqttProperties.getClientId());
-        MqttClient mqttClient = new MqttClient(mqttProperties.getBroker(), mqttProperties.getClientId());
-        mqttClient.setCallback(mqttMessageHandler);
-        mqttClient.connect(options);
-        log.info("MQTT client connected successfully");
-        return mqttClient;
-    }
-} 

+ 0 - 170
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/config/MqttProperties.java

@@ -1,170 +0,0 @@
-package cn.hfln.framework.mqtt.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-
-/**
- * MQTT配置属性
- */
-@Data
-@ConfigurationProperties(prefix = "mqtt")
-public class MqttProperties {
-    /**
-     * 是否启用MQTT
-     */
-    private boolean enabled = true;
-    
-    /**
-     * MQTT服务器地址
-     * 例如:tcp://localhost:1883
-     */
-    private String broker = "tcp://localhost:1883";
-    
-    /**
-     * 客户端ID
-     * 如果为空,会自动生成
-     */
-    private String clientId;
-    
-    /**
-     * 用户名
-     */
-    private String username;
-    
-    /**
-     * 密码
-     */
-    private String password;
-    
-    /**
-     * 连接超时时间(秒)
-     */
-    private int timeout = 30;
-    
-    /**
-     * 心跳间隔(秒)
-     */
-    private int keepalive = 60;
-    
-    /**
-     * 是否清除会话
-     */
-    private boolean cleanSession = true;
-    
-    /**
-     * 是否自动重连
-     */
-    private boolean automaticReconnect = true;
-    
-    /**
-     * 最大重连尝试次数
-     * 设置为-1表示无限重试
-     */
-    private int maxReconnectAttempts = 10;
-    
-    /**
-     * 重连间隔(毫秒)
-     */
-    private long reconnectInterval = 5000;
-    
-    /**
-     * 重连间隔增长因子
-     * 每次重连失败后,下次重连间隔会乘以这个因子
-     * 例如:初始间隔5秒,因子1.5,则重连间隔会变为:5, 7.5, 11.25, ...
-     */
-    private double reconnectBackoffMultiplier = 1.5;
-    
-    /**
-     * 最大重连间隔(毫秒)
-     * 重连间隔增长到这个值后不再增长
-     */
-    private long maxReconnectInterval = 60000;
-    
-    /**
-     * 是否在初始连接失败时抛出异常
-     * 如果为false,则初始连接失败时不会抛出异常,而是在后台进行重连
-     */
-    private boolean failFastOnInitialConnection = false;
-    
-    /**
-     * 连接恢复后是否自动重新订阅之前的主题
-     */
-    private boolean resubscribeOnReconnect = true;
-    
-    /**
-     * 默认QoS级别
-     */
-    private int defaultQos = 1;
-    
-    /**
-     * 默认是否保留消息
-     */
-    private boolean defaultRetained = false;
-    
-    /**
-     * 是否异步发送
-     */
-    private boolean async = true;
-    
-    /**
-     * 是否异步事件
-     */
-    private boolean asyncEvents = true;
-    
-    /**
-     * 默认主题
-     */
-    private String defaultTopic = "default";
-    
-    /**
-     * 订阅主题列表
-     */
-    private String[] subscribeTopics = new String[0];
-    
-    /**
-     * 订阅QoS级别
-     */
-    private int subscribeQos = 1;
-    
-    /**
-     * 完成超时时间(毫秒)
-     */
-    private long completionTimeout = 5000;
-    
-    /**
-     * 连接超时时间(秒)
-     */
-    public int getConnectionTimeout() {
-        return timeout;
-    }
-    
-    /**
-     * 发送消息失败时是否重试
-     */
-    private boolean retryOnPublishFailure = true;
-    
-    /**
-     * 发送消息失败时的最大重试次数
-     */
-    private int maxPublishRetryAttempts = 3;
-    
-    /**
-     * 发送消息重试间隔(毫秒)
-     */
-    private long publishRetryInterval = 1000;
-    
-    /**
-     * 是否启用连接健康检查
-     */
-    private boolean healthCheckEnabled = false;
-    
-    /**
-     * 健康检查间隔(毫秒)
-     */
-    private long healthCheckInterval = 30000;
-    
-    /**
-     * 健康检查主题
-     */
-    private String healthCheckTopic = "$SYS/healthcheck";
-}

+ 0 - 292
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/connection/MqttReconnectManager.java

@@ -1,292 +0,0 @@
-package cn.hfln.framework.mqtt.connection;
-
-import cn.hfln.framework.mqtt.config.MqttProperties;
-import cn.hfln.framework.mqtt.listener.MqttConnectionListener;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.paho.client.mqttv3.MqttClient;
-import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
-import org.eclipse.paho.client.mqttv3.MqttException;
-import org.springframework.beans.factory.DisposableBean;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * MQTT閲嶈繛绠$悊鍣?
- * 璐熻矗澶勭悊MQTT杩炴帴鐨勯噸杩為€昏緫鍜屽仴搴锋鏌?
- */
-@Slf4j
-@Component
-public class MqttReconnectManager implements DisposableBean {
-
-    private final MqttClient mqttClient;
-    private final MqttProperties mqttProperties;
-    private final MqttConnectOptions mqttConnectOptions;
-    private final List<MqttConnectionListener> connectionListeners;
-    
-    private final ScheduledExecutorService scheduler;
-    private final AtomicBoolean reconnecting = new AtomicBoolean(false);
-    private final AtomicInteger reconnectAttempts = new AtomicInteger(0);
-    private long currentReconnectInterval;
-    
-    // 淇濆瓨璁㈤槄鐨勪富棰樺拰QoS
-    private final Map<String, Integer> subscribedTopics = new ConcurrentHashMap<>();
-    
-    @Autowired
-    public MqttReconnectManager(MqttClient mqttClient, 
-                               MqttProperties mqttProperties,
-                               MqttConnectOptions mqttConnectOptions,
-                               List<MqttConnectionListener> connectionListeners) {
-        this.mqttClient = mqttClient;
-        this.mqttProperties = mqttProperties;
-        this.mqttConnectOptions = mqttConnectOptions;
-        this.connectionListeners = connectionListeners;
-        this.currentReconnectInterval = mqttProperties.getReconnectInterval();
-        this.scheduler = Executors.newScheduledThreadPool(1, r -> {
-            Thread thread = new Thread(r, "mqtt-reconnect-thread");
-            thread.setDaemon(true);
-            return thread;
-        });
-        
-        // 鍚姩鍋ュ悍妫€鏌?
-        if (mqttProperties.isHealthCheckEnabled()) {
-            startHealthCheck();
-        }
-    }
-    
-    /**
-     * 澶勭悊杩炴帴涓㈠け浜嬩欢
-     * 
-     * @param cause 杩炴帴涓㈠け鍘熷洜
-     */
-    public void handleConnectionLost(Throwable cause) {
-        log.warn("MQTT connection lost: {}", cause.getMessage());
-        
-        // 閫氱煡杩炴帴鐩戝惉鍣?
-        for (MqttConnectionListener listener : connectionListeners) {
-            try {
-                listener.connectionLost(cause);
-            } catch (Exception e) {
-                log.error("Error notifying connection listener", e);
-            }
-        }
-        
-        // 濡傛灉鍚敤浜嗚嚜鍔ㄩ噸杩烇紝鍒欏紑濮嬮噸杩?
-        if (mqttProperties.isAutomaticReconnect() && !reconnecting.getAndSet(true)) {
-            startReconnect();
-        }
-    }
-    
-    /**
-     * 璁板綍璁㈤槄鐨勪富棰?
-     * 
-     * @param topic 涓婚
-     * @param qos QoS绾у埆
-     */
-    public void recordSubscription(String topic, int qos) {
-        subscribedTopics.put(topic, qos);
-    }
-    
-    /**
-     * 绉婚櫎璁㈤槄鐨勪富棰?
-     * 
-     * @param topic 涓婚
-     */
-    public void removeSubscription(String topic) {
-        subscribedTopics.remove(topic);
-    }
-    
-    /**
-     * 寮€濮嬮噸杩?
-     */
-    private void startReconnect() {
-        reconnectAttempts.set(0);
-        currentReconnectInterval = mqttProperties.getReconnectInterval();
-        scheduleReconnect();
-    }
-    
-    /**
-     * 璋冨害閲嶈繛浠诲姟
-     */
-    private void scheduleReconnect() {
-        int maxAttempts = mqttProperties.getMaxReconnectAttempts();
-        if (maxAttempts > 0 && reconnectAttempts.get() >= maxAttempts) {
-            log.error("Maximum reconnect attempts ({}) reached, giving up reconnecting to MQTT broker", maxAttempts);
-            reconnecting.set(false);
-            
-            // 閫氱煡杩炴帴鐩戝惉鍣?
-            for (MqttConnectionListener listener : connectionListeners) {
-                try {
-                    listener.onConnectionFailed(new Exception("Maximum reconnect attempts reached"));
-                } catch (Exception e) {
-                    log.error("Error notifying connection listener", e);
-                }
-            }
-            return;
-        }
-        
-        log.info("Scheduling reconnect attempt in {} ms", currentReconnectInterval);
-        scheduler.schedule(this::attemptReconnect, currentReconnectInterval, TimeUnit.MILLISECONDS);
-    }
-    
-    /**
-     * 灏濊瘯閲嶈繛
-     */
-    private void attemptReconnect() {
-        try {
-            int attempt = reconnectAttempts.incrementAndGet();
-            log.info("Attempting to reconnect to MQTT broker, attempt: {}/{}", 
-                    attempt, mqttProperties.getMaxReconnectAttempts() > 0 ? 
-                            mqttProperties.getMaxReconnectAttempts() : "unlimited");
-            
-            if (!mqttClient.isConnected()) {
-                mqttClient.connect(mqttConnectOptions);
-                log.info("Successfully reconnected to MQTT broker");
-                
-                // 閲嶆柊璁㈤槄涔嬪墠鐨勪富棰?
-                if (mqttProperties.isResubscribeOnReconnect()) {
-                    resubscribe();
-                }
-                
-                // 閫氱煡杩炴帴鐩戝惉鍣?
-                for (MqttConnectionListener listener : connectionListeners) {
-                    try {
-                        listener.onConnected();
-                    } catch (Exception e) {
-                        log.error("Error notifying connection listener", e);
-                    }
-                }
-                
-                reconnecting.set(false);
-            }
-        } catch (MqttException e) {
-            log.error("Failed to reconnect to MQTT broker: {}, will retry", e.getMessage());
-            
-            // 璁$畻涓嬩竴娆¢噸杩為棿闅?
-            calculateNextReconnectInterval();
-            
-            // 璋冨害涓嬩竴娆¢噸杩?
-            scheduleReconnect();
-        }
-    }
-    
-    /**
-     * 璁$畻涓嬩竴娆¢噸杩為棿闅?
-     */
-    private void calculateNextReconnectInterval() {
-        // 浣跨敤鎸囨暟閫€閬跨畻娉?
-        currentReconnectInterval = Math.min(
-            (long)(currentReconnectInterval * mqttProperties.getReconnectBackoffMultiplier()),
-            mqttProperties.getMaxReconnectInterval()
-        );
-        log.debug("Next reconnect interval: {} ms", currentReconnectInterval);
-    }
-    
-    /**
-     * 閲嶆柊璁㈤槄涔嬪墠鐨勪富棰?
-     */
-    private void resubscribe() {
-        if (subscribedTopics.isEmpty()) {
-            return;
-        }
-        
-        log.info("Resubscribing to {} topics", subscribedTopics.size());
-        
-        subscribedTopics.forEach((topic, qos) -> {
-            try {
-                mqttClient.subscribe(topic, qos);
-                log.debug("Resubscribed to topic: {} with QoS: {}", topic, qos);
-            } catch (MqttException e) {
-                log.error("Failed to resubscribe to topic: {}", topic, e);
-            }
-        });
-    }
-    
-    /**
-     * 鍚姩鍋ュ悍妫€鏌?
-     */
-    private void startHealthCheck() {
-        log.info("Starting MQTT connection health check with interval: {} ms", 
-                mqttProperties.getHealthCheckInterval());
-        
-        scheduler.scheduleAtFixedRate(
-            this::performHealthCheck,
-            mqttProperties.getHealthCheckInterval(),
-            mqttProperties.getHealthCheckInterval(),
-            TimeUnit.MILLISECONDS
-        );
-    }
-    
-    /**
-     * 鎵ц鍋ュ悍妫€鏌?
-     */
-    private void performHealthCheck() {
-        try {
-            if (!mqttClient.isConnected() && !reconnecting.get()) {
-                log.warn("Health check detected disconnected MQTT client, initiating reconnect");
-                handleConnectionLost(new Exception("Health check detected disconnection"));
-            } else {
-                // 鍙互鍦ㄨ繖閲屾坊鍔犻澶栫殑鍋ュ悍妫€鏌ラ€昏緫锛屼緥濡傚彂閫乸ing娑堟伅
-                log.debug("Health check: MQTT connection is {}", 
-                        mqttClient.isConnected() ? "active" : "inactive but reconnecting");
-            }
-        } catch (Exception e) {
-            log.error("Error during MQTT health check", e);
-        }
-    }
-    
-    /**
-     * 鎵嬪姩瑙﹀彂閲嶈繛
-     */
-    public void triggerReconnect() {
-        if (!reconnecting.getAndSet(true)) {
-            log.info("Manually triggering MQTT reconnection");
-            startReconnect();
-        } else {
-            log.debug("Reconnection already in progress, ignoring trigger request");
-        }
-    }
-    
-    /**
-     * 鑾峰彇褰撳墠杩炴帴鐘舵€?
-     * 
-     * @return 杩炴帴鐘舵€佷俊鎭?
-     */
-    public Map<String, Object> getConnectionStatus() {
-        Map<String, Object> status = new HashMap<>();
-        status.put("connected", mqttClient.isConnected());
-        status.put("clientId", mqttClient.getClientId());
-        status.put("serverURI", mqttClient.getServerURI());
-        status.put("reconnecting", reconnecting.get());
-        status.put("reconnectAttempts", reconnectAttempts.get());
-        status.put("subscribedTopics", subscribedTopics.size());
-        return status;
-    }
-    
-    /**
-     * 閿€姣佽祫婧?
-     */
-    @Override
-    public void destroy() {
-        log.info("Shutting down MQTT reconnect manager");
-        scheduler.shutdownNow();
-        try {
-            if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
-                log.warn("Scheduler did not terminate in time");
-            }
-        } catch (InterruptedException e) {
-            Thread.currentThread().interrupt();
-        }
-    }
-} 
-
-

+ 0 - 80
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/converter/JsonMessageConverter.java

@@ -1,80 +0,0 @@
-package cn.hfln.framework.mqtt.converter;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.paho.client.mqttv3.MqttMessage;
-import org.springframework.stereotype.Component;
-
-/**
- * JSON娑堟伅杞崲鍣?
- * 鐢ㄤ簬灏嗗璞¤浆鎹负JSON瀛楃涓诧紝鎴栧皢JSON瀛楃涓茶浆鎹负瀵硅薄
- */
-@Slf4j
-@Component
-public class JsonMessageConverter implements MessageConverter {
-
-    private final ObjectMapper objectMapper = new ObjectMapper();
-
-    /**
-     * 灏嗗璞¤浆鎹负JSON瀛楃涓?
-     * 
-     * @param payload 瀵硅薄
-     * @return JSON瀛楃涓?
-     * @throws JsonProcessingException JSON澶勭悊寮傚父
-     */
-    public String toJson(Object payload) throws JsonProcessingException {
-        if (payload == null) {
-            return null;
-        }
-        
-        if (payload instanceof String) {
-            return (String) payload;
-        }
-        
-        return objectMapper.writeValueAsString(payload);
-    }
-
-    /**
-     * 灏咼SON瀛楃涓茶浆鎹负瀵硅薄
-     * 
-     * @param <T> 鐩爣绫诲瀷
-     * @param json JSON瀛楃涓?
-     * @param clazz 鐩爣绫诲瀷
-     * @return 杞崲鍚庣殑瀵硅薄
-     * @throws JsonProcessingException JSON澶勭悊寮傚父
-     */
-    public <T> T fromJson(String json, Class<T> clazz) throws JsonProcessingException {
-        if (json == null || json.isEmpty()) {
-            return null;
-        }
-        
-        return objectMapper.readValue(json, clazz);
-    }
-    
-    @Override
-    public MqttMessage toMessage(Object payload) {
-        try {
-            String json = toJson(payload);
-            MqttMessage message = new MqttMessage();
-            message.setPayload(json == null ? "null".getBytes() : json.getBytes());
-            return message;
-        } catch (JsonProcessingException e) {
-            log.error("Error converting object to MQTT message", e);
-            throw new RuntimeException("Error converting object to MQTT message", e);
-        }
-    }
-
-    @Override
-    public <T> T fromMessage(MqttMessage message, Class<T> targetType) {
-        try {
-            String json = new String(message.getPayload());
-            return fromJson(json, targetType);
-        } catch (JsonProcessingException e) {
-            log.error("Error converting MQTT message to object", e);
-            throw new RuntimeException("Error converting MQTT message to object", e);
-        }
-    }
-} 
-
-

+ 0 - 27
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/converter/MessageConverter.java

@@ -1,27 +0,0 @@
-package cn.hfln.framework.mqtt.converter;
-
-import org.eclipse.paho.client.mqttv3.MqttMessage;
-
-/**
- * MQTT娑堟伅杞崲鍣ㄦ帴鍙?
- */
-public interface MessageConverter {
-    /**
-     * 灏嗗璞¤浆鎹负MQTT娑堟伅
-     *
-     * @param payload 娑堟伅鍐呭
-     * @return MqttMessage
-     */
-    MqttMessage toMessage(Object payload);
-
-    /**
-     * 灏哅QTT娑堟伅杞崲涓哄璞?
-     *
-     * @param message MQTT娑堟伅
-     * @param targetType 鐩爣绫诲瀷
-     * @return 杞崲鍚庣殑瀵硅薄
-     */
-    <T> T fromMessage(MqttMessage message, Class<T> targetType);
-} 
-
-

+ 0 - 28
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/exception/MqttExceptionHandler.java

@@ -1,28 +0,0 @@
-package cn.hfln.framework.mqtt.exception;
-
-import org.eclipse.paho.client.mqttv3.MqttException;
-import java.util.function.Consumer;
-
-public class MqttExceptionHandler {
-    public static void handleException(MqttException ex, Consumer<MqttException> recoverAction) {
-        // 默认空实现
-        if (recoverAction != null) {
-            recoverAction.accept(ex);
-        }
-    }
-
-    public static boolean isRecoverableByReconnect(MqttException ex) {
-        // 默认全部不可恢复
-        return false;
-    }
-
-    public static String getDetailedErrorMessage(MqttException ex) {
-        // 返回异常信息
-        return ex != null ? ex.getMessage() : "";
-    }
-
-    public static String getRecommendedAction(MqttException ex) {
-        // 返回默认建议
-        return "请检查MQTT连接配置或网络状态";
-    }
-}

+ 0 - 225
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/gateway/DefaultMqttGateway.java

@@ -1,225 +0,0 @@
-package cn.hfln.framework.mqtt.gateway;
-
-import cn.hfln.framework.mqtt.template.MqttTemplate;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.paho.client.mqttv3.MqttClient;
-import org.eclipse.paho.client.mqttv3.MqttException;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-
-/**
- * MQTT网关默认实现
- * 使用MqttTemplate实现MQTT消息发送功能
- */
-@Slf4j
-@Component
-public class DefaultMqttGateway implements MqttGateway {
-
-    private final MqttTemplate mqttTemplate;
-    private final MqttClient mqttClient;
-
-    @Autowired
-    public DefaultMqttGateway(MqttTemplate mqttTemplate, MqttClient mqttClient) {
-        this.mqttTemplate = mqttTemplate;
-        this.mqttClient = mqttClient;
-    }
-
-    @Override
-    public void initialize() {
-        log.info("MQTT Gateway initialized");
-    }
-
-    @Override
-    public void publish(String topic, Object payload) {
-        try {
-            if (payload instanceof String) {
-                mqttTemplate.send(topic, (String) payload);
-            } else {
-                mqttTemplate.sendJson(topic, payload);
-            }
-            log.debug("Message published to topic: {}", topic);
-        } catch (Exception e) {
-            log.error("Error publishing message to topic: {}", topic, e);
-        }
-    }
-
-    @Override
-    public void publish(String topic, Object payload, int qos, boolean retain) {
-        try {
-            if (payload instanceof String) {
-                mqttTemplate.send(topic, (String) payload, qos, retain);
-            } else {
-                mqttTemplate.sendJson(topic, payload, qos, retain);
-            }
-            log.debug("Message published to topic: {} with QoS: {}, retain: {}", topic, qos, retain);
-        } catch (Exception e) {
-            log.error("Error publishing message to topic: {}", topic, e);
-        }
-    }
-
-    @Override
-    public void sendMessage(String topic, String message) {
-        try {
-            mqttTemplate.send(topic, message);
-            log.debug("Message sent to topic: {}", topic);
-        } catch (Exception e) {
-            log.error("Error sending message to topic: {}", topic, e);
-        }
-    }
-
-    @Override
-    public void sendMessage(String topic, String message, int qos, boolean retain) {
-        try {
-            mqttTemplate.send(topic, message, qos, retain);
-            log.debug("Message sent to topic: {} with QoS: {}, retain: {}", topic, qos, retain);
-        } catch (Exception e) {
-            log.error("Error sending message to topic: {}", topic, e);
-        }
-    }
-
-    @Override
-    public void publishJson(String topic, Object payload) {
-        try {
-            mqttTemplate.sendJson(topic, payload);
-            log.debug("JSON message published to topic: {}", topic);
-        } catch (Exception e) {
-            log.error("Error publishing JSON message to topic: {}", topic, e);
-        }
-    }
-
-    @Override
-    public void publishJson(String topic, Object payload, int qos, boolean retain) {
-        try {
-            mqttTemplate.sendJson(topic, payload, qos, retain);
-            log.debug("JSON message published to topic: {} with QoS: {}, retain: {}", topic, qos, retain);
-        } catch (Exception e) {
-            log.error("Error publishing JSON message to topic: {}", topic, e);
-        }
-    }
-
-    @Override
-    public void sendSync(String topic, Object payload) throws Exception {
-        try {
-            if (payload instanceof String) {
-                mqttTemplate.sendSync(topic, (String) payload);
-            } else {
-                mqttTemplate.sendJsonSync(topic, payload);
-            }
-            log.debug("Message sent synchronously to topic: {}", topic);
-        } catch (MqttException e) {
-            log.error("Error sending synchronous message to topic: {}", topic, e);
-            throw e;
-        }
-    }
-
-    @Override
-    public void subscribe(String topic, int qos) {
-        try {
-            mqttClient.subscribe(topic, qos);
-            log.info("Subscribed to topic: {} with QoS: {}", topic, qos);
-        } catch (MqttException e) {
-            log.error("Error subscribing to topic: {}", topic, e);
-        }
-    }
-
-    @Override
-    public void unsubscribe(String topic) {
-        try {
-            mqttClient.unsubscribe(topic);
-            log.info("Unsubscribed from topic: {}", topic);
-        } catch (MqttException e) {
-            log.error("Error unsubscribing from topic: {}", topic, e);
-        }
-    }
-
-    @Override
-    public boolean isConnected() {
-        return mqttClient.isConnected();
-    }
-
-    @Override
-    public void disconnect() {
-        try {
-            mqttClient.disconnect();
-            log.info("MQTT client disconnected");
-        } catch (MqttException e) {
-            log.error("Error disconnecting MQTT client", e);
-        }
-    }
-    
-    /**
-     * 发送通用消息
-     * 
-     * @param topic 主题
-     * @param messageType 消息类型
-     * @param messageData 消息数据
-     */
-    @Override
-    public void sendGenericMessage(String topic, String messageType, Map<String, Object> messageData) {
-        try {
-            Map<String, Object> payload = new HashMap<>();
-            payload.put("message_type", messageType);
-            payload.put("timestamp", System.currentTimeMillis());
-            
-            if (messageData != null) {
-                payload.putAll(messageData);
-            }
-            
-            publishJson(topic, payload);
-        } catch (Exception e) {
-            log.error("Error sending generic message to topic: {}", topic, e);
-        }
-    }
-    
-    /**
-     * 发送命令消息
-     * 
-     * @param topic 主题
-     * @param command 命令
-     * @param params 参数
-     */
-    @Override
-    public void sendCommand(String topic, String command, Map<String, Object> params) {
-        try {
-            Map<String, Object> payload = new HashMap<>();
-            payload.put("command", command);
-            payload.put("timestamp", System.currentTimeMillis());
-            
-            if (params != null) {
-                payload.put("params", params);
-            }
-            
-            publishJson(topic, payload);
-        } catch (Exception e) {
-            log.error("Error sending command to topic: {}", topic, e);
-        }
-    }
-    
-    /**
-     * 发送响应消息
-     * 
-     * @param topic 主题
-     * @param code 响应码
-     * @param data 响应数据
-     */
-    @Override
-    public void sendResponse(String topic, int code, Map<String, Object> data) {
-        try {
-            Map<String, Object> payload = new HashMap<>();
-            payload.put("code", code);
-            payload.put("timestamp", System.currentTimeMillis());
-            
-            if (data != null) {
-                payload.putAll(data);
-            }
-            
-            publishJson(topic, payload);
-        } catch (Exception e) {
-            log.error("Error sending response to topic: {}", topic, e);
-        }
-    }
-} 

+ 0 - 132
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/gateway/MqttGateway.java

@@ -1,132 +0,0 @@
-package cn.hfln.framework.mqtt.gateway;
-
-import java.util.Map;
-
-/**
- * MQTT网关接口
- * 定义MQTT消息发送的基本功能
- */
-public interface MqttGateway {
-
-    /**
-     * 初始化MQTT客户端
-     */
-    void initialize();
-    
-    /**
-     * 发布MQTT消息
-     * 
-     * @param topic 主题
-     * @param payload 消息内容
-     */
-    void publish(String topic, Object payload);
-    
-    /**
-     * 发布MQTT消息(指定QoS和保留标志)
-     * 
-     * @param topic 主题
-     * @param payload 消息内容
-     * @param qos QoS级别(0,1,2)
-     * @param retain 是否保留消息
-     */
-    void publish(String topic, Object payload, int qos, boolean retain);
-    
-    /**
-     * 发布MQTT消息(字符串内容)
-     * 
-     * @param topic 主题
-     * @param message 消息内容
-     */
-    void sendMessage(String topic, String message);
-    
-    /**
-     * 发布MQTT消息(字符串内容,指定QoS和保留标志)
-     * 
-     * @param topic 主题
-     * @param message 消息内容
-     * @param qos QoS级别(0,1,2)
-     * @param retain 是否保留消息
-     */
-    void sendMessage(String topic, String message, int qos, boolean retain);
-    
-    /**
-     * 发布JSON格式的MQTT消息
-     * 
-     * @param topic 主题
-     * @param payload 消息内容对象
-     */
-    void publishJson(String topic, Object payload);
-    
-    /**
-     * 发布JSON格式的MQTT消息(指定QoS和保留标志)
-     * 
-     * @param topic 主题
-     * @param payload 消息内容对象
-     * @param qos QoS级别(0,1,2)
-     * @param retain 是否保留消息
-     */
-    void publishJson(String topic, Object payload, int qos, boolean retain);
-    
-    /**
-     * 同步发送消息
-     * 
-     * @param topic 主题
-     * @param payload 消息内容
-     * @throws Exception 发送异常
-     */
-    void sendSync(String topic, Object payload) throws Exception;
-    
-    /**
-     * 订阅主题
-     * 
-     * @param topic 主题
-     * @param qos QoS级别
-     */
-    void subscribe(String topic, int qos);
-    
-    /**
-     * 取消订阅主题
-     * 
-     * @param topic 主题
-     */
-    void unsubscribe(String topic);
-    
-    /**
-     * 判断是否已连接
-     * 
-     * @return 是否已连接
-     */
-    boolean isConnected();
-    
-    /**
-     * 关闭连接
-     */
-    void disconnect();
-    
-    /**
-     * 发送通用消息
-     * 
-     * @param topic 主题
-     * @param messageType 消息类型
-     * @param messageData 消息数据
-     */
-    void sendGenericMessage(String topic, String messageType, Map<String, Object> messageData);
-    
-    /**
-     * 发送命令消息
-     * 
-     * @param topic 主题
-     * @param command 命令
-     * @param params 参数
-     */
-    void sendCommand(String topic, String command, Map<String, Object> params);
-    
-    /**
-     * 发送响应消息
-     * 
-     * @param topic 主题
-     * @param code 响应码
-     * @param data 响应数据
-     */
-    void sendResponse(String topic, int code, Map<String, Object> data);
-} 

+ 0 - 0
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/handler/GenericMqttMessageHandler.java


+ 0 - 22
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/handler/MqttMessageHandler.java

@@ -1,22 +0,0 @@
-package cn.hfln.framework.mqtt.handler;
-
-import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
-import org.eclipse.paho.client.mqttv3.MqttCallback;
-import org.eclipse.paho.client.mqttv3.MqttMessage;
-
-public class MqttMessageHandler implements MqttCallback {
-    @Override
-    public void connectionLost(Throwable cause) {
-        // 连接丢失时的处理
-    }
-
-    @Override
-    public void messageArrived(String topic, MqttMessage message) {
-        // 收到消息时的处理
-    }
-
-    @Override
-    public void deliveryComplete(IMqttDeliveryToken token) {
-        // 消息发送完成时的处理
-    }
-}

+ 0 - 102
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/handler/MqttMessageRouter.java

@@ -1,102 +0,0 @@
-package cn.hfln.framework.mqtt.handler;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.regex.Pattern;
-
-/**
- * MQTT消息路由器
- * 根据主题模式匹配将消息路由到对应的处理器
- */
-@Slf4j
-@Component
-public class MqttMessageRouter {
-
-    // 主题模式和处理器的映射关系
-    private final Map<Pattern, MqttTopicHandler> handlerMap = new ConcurrentHashMap<>();
-
-    /**
-     * 注册主题处理器
-     * @param topicPattern 主题模式(正则表达式)
-     * @param handler 处理器
-     * @return 路由器实例,支持链式调用
-     */
-    public MqttMessageRouter register(String topicPattern, MqttTopicHandler handler) {
-        Pattern pattern = Pattern.compile(topicPattern);
-        handlerMap.put(pattern, handler);
-        log.info("Registered MQTT topic handler for pattern: {}", topicPattern);
-        return this;
-    }
-
-    /**
-     * 注册主题处理器
-     * @param pattern 主题模式(已编译的正则表达式)
-     * @param handler 处理器
-     * @return 路由器实例,支持链式调用
-     */
-    public MqttMessageRouter register(Pattern pattern, MqttTopicHandler handler) {
-        handlerMap.put(pattern, handler);
-        log.info("Registered MQTT topic handler for pattern: {}", pattern.pattern());
-        return this;
-    }
-
-    /**
-     * 取消注册主题处理器
-     * @param topicPattern 主题模式(正则表达式)
-     * @return 路由器实例,支持链式调用
-     */
-    public MqttMessageRouter unregister(String topicPattern) {
-        for (Pattern pattern : handlerMap.keySet()) {
-            if (pattern.pattern().equals(topicPattern)) {
-                handlerMap.remove(pattern);
-                log.info("Unregistered MQTT topic handler for pattern: {}", topicPattern);
-                break;
-            }
-        }
-        return this;
-    }
-
-    /**
-     * 路由消息到相应的处理器
-     * @param topic 消息主题
-     * @param payload 消息内容
-     * @return 是否找到匹配的处理器
-     */
-    public boolean route(String topic, String payload) {
-        boolean handled = false;
-        
-        for (Map.Entry<Pattern, MqttTopicHandler> entry : handlerMap.entrySet()) {
-            Pattern pattern = entry.getKey();
-            MqttTopicHandler handler = entry.getValue();
-            
-            if (pattern.matcher(topic).matches()) {
-                try {
-                    handler.handle(topic, payload);
-                    handled = true;
-                    log.debug("Routed MQTT message to handler: topic={}, pattern={}", topic, pattern.pattern());
-                } catch (Exception e) {
-                    log.error("Error handling MQTT message: topic={}, pattern={}", topic, pattern.pattern(), e);
-                }
-            }
-        }
-        
-        if (!handled) {
-            log.debug("No handler found for MQTT topic: {}", topic);
-        }
-        
-        return handled;
-    }
-
-    /**
-     * 清除所有已注册的处理器
-     */
-    public void clear() {
-        handlerMap.clear();
-        log.info("Cleared all MQTT topic handlers");
-    }
-} 
-
-

+ 0 - 120
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/handler/MqttSubscribeProcessor.java

@@ -1,120 +0,0 @@
-package cn.hfln.framework.mqtt.handler;
-
-import cn.hfln.framework.mqtt.annotation.MqttSubscribe;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.paho.client.mqttv3.MqttClient;
-import org.eclipse.paho.client.mqttv3.MqttException;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.config.BeanPostProcessor;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Component;
-import org.springframework.util.ReflectionUtils;
-
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Pattern;
-
-@Slf4j
-@Component
-public class MqttSubscribeProcessor implements BeanPostProcessor {
-
-    private final Map<String, Method> topicMethodMap = new HashMap<>();
-    
-    @Autowired
-    @Lazy
-    private MqttClient mqttClient;
-
-    @Autowired
-    private ApplicationContext applicationContext;
-
-    @Override
-    public Object postProcessAfterInitialization(Object bean, String beanName) {
-//        log.info("Processing bean: {} for MQTT subscriptions", beanName);
-
-        Class<?> beanClass = bean.getClass();
-        
-        // 处理类级别的注解
-        MqttSubscribe classAnnotation = beanClass.getAnnotation(MqttSubscribe.class);
-        if (classAnnotation != null) {
-            processMqttSubscribe(bean, beanClass, classAnnotation);
-        }
-
-        // 处理方法级别的订阅
-        ReflectionUtils.doWithMethods(beanClass, method -> {
-            MqttSubscribe annotation = method.getAnnotation(MqttSubscribe.class);
-            if (annotation != null) {
-                processMqttSubscribe(bean, method, annotation);
-            }
-        });
-
-        return bean;
-    }
-
-    private void processMqttSubscribe(Object bean, Object target, MqttSubscribe annotation) {
-        String topic = annotation.topic();
-        int qos = annotation.qos();
-        
-        if (!mqttClient.isConnected()) {
-            log.error("MQTT client is not connected, cannot subscribe to topic: {}", topic);
-            return;
-        }
-
-        try {
-//            log.info("Subscribing to topic: {} with QoS: {}", topic, qos);
-            mqttClient.subscribe(topic, qos);
-            
-            if (target instanceof Method) {
-                topicMethodMap.put(topic, (Method) target);
-            } else if (target instanceof Class) {
-                // 对于类级别的注解,需要找到合适的处理方法
-                // 首先尝试精确匹配
-                Method method = findHandlerMethod((Class<?>) target);
-                if (method != null) {
-                    topicMethodMap.put(topic, method);
-                }
-            }
-            
-//            log.info("Successfully subscribed to topic: {} with QoS: {}", topic, qos);
-        } catch (MqttException e) {
-            log.error("Failed to subscribe to topic: {}", topic, e);
-        }
-    }
-
-    private Method findHandlerMethod(Class<?> targetClass) {
-        for (Method method : targetClass.getMethods()) {
-            if (method.getParameterCount() == 1 && 
-                (method.getParameterTypes()[0] == String.class || 
-                 method.getParameterTypes()[0] == byte[].class)) {
-                return method;
-            }
-        }
-        return null;
-    }
-
-    public Method getMethodForTopic(String topic) {
-        // 对于类级别的注解,需要找到合适的处理方法
-        // 首先尝试精确匹配
-        Method method = topicMethodMap.get(topic);
-        if (method != null) {
-            return method;
-        }
-
-        // 如果没有精确匹配,则尝试通配符匹配
-        for (Map.Entry<String, Method> entry : topicMethodMap.entrySet()) {
-            String pattern = entry.getKey()
-                    .replace("+", "[^/]+")  // 对于 + ,需要替换为 [^/]+ ,以匹配除 / 之外的任何字符
-                    .replace("#", ".*");     // 对于 # ,需要替换为 .* ,以匹配任何字符串
-            if (Pattern.matches(pattern, topic)) {
-//                log.info("Found matching method for topic: {} using pattern: {}", topic, pattern);
-                return entry.getValue();
-            }
-        }
-
-        log.warn("No method found for topic: {}", topic);
-        return null;
-    }
-} 
-
-

+ 0 - 243
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/handler/MqttSubscriberProcessor.java

@@ -1,243 +0,0 @@
-package cn.hfln.framework.mqtt.handler;
-
-import cn.hfln.framework.mqtt.annotation.MqttSubscriber;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.paho.client.mqttv3.MqttClient;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.DisposableBean;
-import org.springframework.beans.factory.SmartInitializingSingleton;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
-import org.springframework.messaging.Message;
-import org.springframework.messaging.MessageHandler;
-import org.springframework.messaging.MessagingException;
-import org.springframework.stereotype.Component;
-
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * MQTT订阅处理器
- * 扫描并处理带有@MqttSubscriber注解的方法
- */
-@Slf4j
-@Component
-public class MqttSubscriberProcessor implements ApplicationContextAware, SmartInitializingSingleton, DisposableBean {
-    
-    private ApplicationContext applicationContext;
-    private final MqttPahoMessageDrivenChannelAdapter mqttInbound;
-    private final MqttClient mqttClient;
-    private final MessageHandler messageHandler;
-    
-    // 保存主题和订阅方法的映射关系
-    private final Map<String, SubscriberMethod> topicSubscriberMap = new ConcurrentHashMap<>();
-    
-    public MqttSubscriberProcessor(MqttPahoMessageDrivenChannelAdapter mqttInbound, MqttClient mqttClient) {
-        this.mqttInbound = mqttInbound;
-        this.mqttClient = mqttClient;
-        
-        // 创建消息处理器
-        this.messageHandler = message -> {
-            try {
-                processMessage(message);
-            } catch (Exception e) {
-                log.error("Error processing MQTT message: {}", e.getMessage(), e);
-            }
-        };
-    }
-    
-    private void processMessage(Message<?> message) {
-        String receivedTopic = (String) message.getHeaders().get("mqtt_receivedTopic");
-        if (receivedTopic == null) {
-            log.warn("Received MQTT message without topic header");
-            return;
-        }
-        
-        // 查找对应的订阅方法
-        SubscriberMethod subscriberMethod = findSubscriberMethod(receivedTopic);
-        if (subscriberMethod == null) {
-            log.debug("No subscriber found for topic: {}", receivedTopic);
-            return;
-        }
-        
-        try {
-            // 调用订阅方法
-            invokeSubscriberMethod(subscriberMethod, receivedTopic, message);
-        } catch (Exception e) {
-            log.error("Error invoking MQTT subscriber method: {}", e.getMessage(), e);
-        }
-    }
-    
-    private SubscriberMethod findSubscriberMethod(String receivedTopic) {
-        // 精确匹配
-        if (topicSubscriberMap.containsKey(receivedTopic)) {
-            return topicSubscriberMap.get(receivedTopic);
-        }
-        
-        // 模式匹配
-        for (Map.Entry<String, SubscriberMethod> entry : topicSubscriberMap.entrySet()) {
-            if (matchTopic(entry.getKey(), receivedTopic)) {
-                return entry.getValue();
-            }
-        }
-        
-        return null;
-    }
-    
-    /**
-     * 匹配主题
-     * 支持通配符 + 和 #
-     * + 匹配一个层级
-     * # 匹配多个层级
-     */
-    private boolean matchTopic(String pattern, String topic) {
-        String[] patternSegments = pattern.split("/");
-        String[] topicSegments = topic.split("/");
-        
-        if (patternSegments.length > topicSegments.length) {
-            return false;
-        }
-        
-        for (int i = 0; i < patternSegments.length; i++) {
-            if (i == patternSegments.length - 1 && patternSegments[i].equals("#")) {
-                return true;
-            }
-            
-            if (!patternSegments[i].equals("+") && !patternSegments[i].equals(topicSegments[i])) {
-                return false;
-            }
-        }
-        
-        return patternSegments.length == topicSegments.length;
-    }
-    
-    private void invokeSubscriberMethod(SubscriberMethod subscriberMethod, String topic, Message<?> message) throws Exception {
-        Method method = subscriberMethod.getMethod();
-        Object bean = subscriberMethod.getBean();
-        
-        if (method.getParameterCount() == 1) {
-            // 一个参数:消息内容
-            Object payload = message.getPayload();
-            method.invoke(bean, payload);
-        } else if (method.getParameterCount() == 2) {
-            // 两个参数:主题和消息内容
-            Object payload = message.getPayload();
-            method.invoke(bean, topic, payload);
-        } else {
-            log.warn("Invalid subscriber method parameter count: {}", method.getParameterCount());
-        }
-    }
-    
-    @Override
-    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
-        this.applicationContext = applicationContext;
-    }
-    
-    @Override
-    public void afterSingletonsInstantiated() {
-        // 扫描所有Bean,查找带有@MqttSubscriber注解的方法
-        String[] beanNames = applicationContext.getBeanDefinitionNames();
-        for (String beanName : beanNames) {
-            Object bean = applicationContext.getBean(beanName);
-            scanSubscriberMethods(bean);
-        }
-        
-        // 设置消息通道
-        mqttInbound.setOutputChannelName("mqttInputChannel");
-    }
-    
-    private void scanSubscriberMethods(Object bean) {
-        Class<?> beanClass = bean.getClass();
-        for (Method method : beanClass.getMethods()) {
-            MqttSubscriber mqttSubscriber = method.getAnnotation(MqttSubscriber.class);
-            if (mqttSubscriber != null) {
-                registerSubscriberMethod(bean, method, mqttSubscriber);
-            }
-        }
-    }
-    
-    private void registerSubscriberMethod(Object bean, Method method, MqttSubscriber mqttSubscriber) {
-        // 检查方法参数
-        if (method.getParameterCount() != 1 && method.getParameterCount() != 2) {
-            log.error("MQTT subscriber method should have 1 or 2 parameters: {}.{}",
-                    bean.getClass().getName(), method.getName());
-            return;
-        }
-        
-        if (method.getParameterCount() == 2 && !method.getParameterTypes()[0].equals(String.class)) {
-            log.error("First parameter of MQTT subscriber method should be String (topic): {}.{}",
-                    bean.getClass().getName(), method.getName());
-            return;
-        }
-        
-        // 注册订阅方法
-        SubscriberMethod subscriberMethod = new SubscriberMethod(bean, method, mqttSubscriber);
-        topicSubscriberMap.put(mqttSubscriber.topic(), subscriberMethod);
-        
-        // 添加订阅
-        String formattedTopic = formatTopic(mqttSubscriber);
-        try {
-            log.info("Subscribe to MQTT topic: {}, QoS: {}", formattedTopic, mqttSubscriber.qos());
-            
-            // 添加到MQTT入站通道
-            mqttInbound.addTopic(formattedTopic, mqttSubscriber.qos());
-        } catch (Exception e) {
-            log.error("Error subscribing to topic: {}", formattedTopic, e);
-        }
-        
-        log.info("Registered MQTT subscriber: {}.{} for topic: {}",
-                bean.getClass().getName(), method.getName(), mqttSubscriber.topic());
-    }
-    
-    private String formatTopic(MqttSubscriber mqttSubscriber) {
-        if (mqttSubscriber.shared()) {
-            return "$share/" + mqttSubscriber.group() + "/" + mqttSubscriber.topic();
-        } else {
-            return mqttSubscriber.topic();
-        }
-    }
-    
-    @Override
-    public void destroy() throws Exception {
-        if (mqttClient != null && mqttClient.isConnected()) {
-            for (String topic : topicSubscriberMap.keySet()) {
-                try {
-                    mqttClient.unsubscribe(topic);
-                    log.info("Unsubscribed from topic: {}", topic);
-                } catch (Exception e) {
-                    log.error("Error unsubscribing from topic: {}", topic, e);
-                }
-            }
-        }
-    }
-    
-    /**
-     * 订阅方法信息类
-     */
-    private static class SubscriberMethod {
-        private final Object bean;
-        private final Method method;
-        private final MqttSubscriber mqttSubscriber;
-        
-        public SubscriberMethod(Object bean, Method method, MqttSubscriber mqttSubscriber) {
-            this.bean = bean;
-            this.method = method;
-            this.mqttSubscriber = mqttSubscriber;
-        }
-        
-        public Object getBean() {
-            return bean;
-        }
-        
-        public Method getMethod() {
-            return method;
-        }
-        
-        public MqttSubscriber getMqttSubscriber() {
-            return mqttSubscriber;
-        }
-    }
-} 

+ 0 - 18
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/handler/MqttTopicHandler.java

@@ -1,18 +0,0 @@
-package cn.hfln.framework.mqtt.handler;
-
-/**
- * MQTT主题处理器接口
- * 定义处理特定主题MQTT消息的方法
- */
-public interface MqttTopicHandler {
-    
-    /**
-     * 处理MQTT消息
-     * @param topic 消息主题
-     * @param payload 消息内容
-     * @throws Exception 处理异常
-     */
-    void handle(String topic, String payload) throws Exception;
-} 
-
-

+ 0 - 33
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/interceptor/DefaultMqttMessageInterceptor.java

@@ -1,33 +0,0 @@
-package cn.hfln.framework.mqtt.interceptor;
-
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.paho.client.mqttv3.MqttMessage;
-import org.springframework.stereotype.Component;
-
-@Slf4j
-@Component
-public class DefaultMqttMessageInterceptor implements MqttMessageInterceptor {
-    @Override
-    public boolean preSend(String topic, MqttMessage message) {
-//        log.debug("Pre-send message to topic: {}", topic);
-        return true;
-    }
-
-    @Override
-    public void postSend(String topic, MqttMessage message) {
-        log.debug("Post-send message to topic: {}", topic);
-    }
-
-    @Override
-    public boolean preReceive(String topic, MqttMessage message) {
-//        log.debug("Pre-receive message from topic: {}", topic);
-        return true;
-    }
-
-    @Override
-    public void postReceive(String topic, MqttMessage message) {
-//        log.debug("Post-receive message from topic: {}", topic);
-    }
-} 
-
-

+ 0 - 67
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/interceptor/MqttMessageInterceptor.java

@@ -1,67 +0,0 @@
-package cn.hfln.framework.mqtt.interceptor;
-
-import org.eclipse.paho.client.mqttv3.MqttMessage;
-
-/**
- * MQTT娑堟伅鎷︽埅鍣ㄦ帴鍙?
- * 鐢ㄤ簬鍦ㄦ秷鎭彂閫佸拰鎺ユ敹鍓嶅悗杩涜澶勭悊
- */
-public interface MqttMessageInterceptor {
-    
-    /**
-     * 娑堟伅鍙戦€佸墠澶勭悊
-     * 
-     * @param topic 涓婚
-     * @param message 娑堟伅
-     * @return 鏄惁缁х画鍙戦€?
-     */
-    boolean preSend(String topic, MqttMessage message);
-    
-    /**
-     * 娑堟伅鍙戦€佸悗澶勭悊
-     * 
-     * @param topic 涓婚
-     * @param message 娑堟伅
-     */
-    void postSend(String topic, MqttMessage message);
-    
-    /**
-     * 娑堟伅鎺ユ敹鍓嶅鐞?
-     * 
-     * @param topic 涓婚
-     * @param message 娑堟伅
-     * @return 鏄惁缁х画澶勭悊
-     */
-    boolean preReceive(String topic, MqttMessage message);
-    
-    /**
-     * 娑堟伅鎺ユ敹鍚庡鐞?
-     * 
-     * @param topic 涓婚
-     * @param message 娑堟伅
-     */
-    void postReceive(String topic, MqttMessage message);
-    
-    /**
-     * 娑堟伅鍙戝竷鍓嶅鐞?
-     * 
-     * @param topic 涓婚
-     * @param payload 娑堟伅鍐呭
-     * @return 澶勭悊鍚庣殑娑堟伅鍐呭
-     */
-    default String beforePublish(String topic, String payload) {
-        return payload;
-    }
-    
-    /**
-     * 娑堟伅鍙戝竷鍚庡鐞?
-     * 
-     * @param topic 涓婚
-     * @param payload 娑堟伅鍐呭
-     */
-    default void afterPublish(String topic, String payload) {
-        // 榛樿绌哄疄鐜?
-    }
-}
-
-

+ 0 - 25
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/listener/DefaultMqttConnectionListener.java

@@ -1,25 +0,0 @@
-package cn.hfln.framework.mqtt.listener;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-@Slf4j
-@Component
-public class DefaultMqttConnectionListener implements MqttConnectionListener {
-    @Override
-    public void onConnected() {
-        log.info("MQTT client connected successfully");
-    }
-
-    @Override
-    public void onDisconnected(Throwable cause) {
-        log.warn("MQTT client disconnected", cause);
-    }
-
-    @Override
-    public void onConnectionFailed(Throwable cause) {
-        log.error("MQTT client connection failed", cause);
-    }
-} 
-
-

+ 0 - 17
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/listener/DefaultMqttMessageListener.java

@@ -1,17 +0,0 @@
-package cn.hfln.framework.mqtt.listener;
-
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.paho.client.mqttv3.MqttMessage;
-import org.springframework.stereotype.Component;
-
-@Slf4j
-@Component
-public class DefaultMqttMessageListener implements MqttMessageListener {
-    @Override
-    public void onMessage(String topic, MqttMessage message) {
-        log.info("Received message on topic: {}", topic);
-        log.info("Message content: {}", new String(message.getPayload()));
-    }
-} 
-
-

+ 0 - 47
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/listener/MqttConnectionListener.java

@@ -1,47 +0,0 @@
-package cn.hfln.framework.mqtt.listener;
-
-import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
-
-/**
- * MQTT连接状态监听器接口
- */
-public interface MqttConnectionListener {
-    /**
-     * 连接成功回调
-     */
-    void onConnected();
-
-    /**
-     * 连接断开回调
-     *
-     * @param cause 断开原因
-     */
-    void onDisconnected(Throwable cause);
-
-    /**
-     * 连接失败回调
-     *
-     * @param cause 失败原因
-     */
-    void onConnectionFailed(Throwable cause);
-    
-    /**
-     * 连接丢失回调
-     *
-     * @param cause 丢失原因
-     */
-    default void connectionLost(Throwable cause) {
-        onDisconnected(cause);
-    }
-    
-    /**
-     * 消息发送完成回调
-     *
-     * @param token 消息发送令牌
-     */
-    default void deliveryComplete(IMqttDeliveryToken token) {
-        // 榛樿绌哄疄鐜
-    }
-} 
-
-

+ 0 - 18
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/listener/MqttMessageListener.java

@@ -1,18 +0,0 @@
-package cn.hfln.framework.mqtt.listener;
-
-import org.eclipse.paho.client.mqttv3.MqttMessage;
-
-/**
- * MQTT消息监听器接口
- */
-public interface MqttMessageListener {
-    /**
-     * 处理接收到的消息
-     *
-     * @param topic   主题
-     * @param message 消息
-     */
-    void onMessage(String topic, MqttMessage message);
-} 
-
-

+ 0 - 540
mqtt-spring-boot-starter/src/main/java/cn/hfln/framework/mqtt/template/MqttTemplate.java

@@ -1,540 +0,0 @@
-package cn.hfln.framework.mqtt.template;
-
-import cn.hfln.framework.mqtt.config.MqttProperties;
-import cn.hfln.framework.mqtt.connection.MqttReconnectManager;
-import cn.hfln.framework.mqtt.converter.JsonMessageConverter;
-import cn.hfln.framework.mqtt.converter.MessageConverter;
-import cn.hfln.framework.mqtt.exception.MqttExceptionHandler;
-import cn.hfln.framework.mqtt.interceptor.MqttMessageInterceptor;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.paho.client.mqttv3.MqttClient;
-import org.eclipse.paho.client.mqttv3.MqttException;
-import org.eclipse.paho.client.mqttv3.MqttMessage;
-import org.springframework.beans.factory.DisposableBean;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
-import org.springframework.integration.mqtt.support.MqttHeaders;
-import org.springframework.messaging.Message;
-import org.springframework.messaging.support.MessageBuilder;
-import org.springframework.stereotype.Component;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * MQTT消息模板
- * 提供发送MQTT消息的便捷方法
- */
-@Slf4j
-@Component
-public class MqttTemplate implements DisposableBean {
-    private final MqttPahoMessageHandler mqttOutbound;
-    private final JsonMessageConverter jsonConverter;
-    private final List<MqttMessageInterceptor> interceptors;
-    private final MqttClient mqttClient;
-    private final MessageConverter messageConverter;
-    private final MqttProperties mqttProperties;
-    private final MqttReconnectManager reconnectManager;
-    
-    // 用于重试发送消息的线程池
-    private final ScheduledExecutorService retryExecutor;
-    
-    // 消息发送统计
-    private final AtomicInteger totalMessagesSent = new AtomicInteger(0);
-    private final AtomicInteger failedMessages = new AtomicInteger(0);
-    private final AtomicInteger retriedMessages = new AtomicInteger(0);
-
-    @Autowired(required = false)
-    public MqttTemplate(MqttPahoMessageHandler mqttOutbound, JsonMessageConverter jsonConverter) {
-        this.mqttOutbound = mqttOutbound;
-        this.jsonConverter = jsonConverter;
-        this.interceptors = Collections.emptyList();
-        this.mqttClient = null;
-        this.messageConverter = null;
-        this.mqttProperties = null;
-        this.reconnectManager = null;
-        this.retryExecutor = null;
-    }
-
-    @Autowired(required = false)
-    public MqttTemplate(MqttPahoMessageHandler mqttOutbound, JsonMessageConverter jsonConverter, 
-                      List<MqttMessageInterceptor> interceptors) {
-        this.mqttOutbound = mqttOutbound;
-        this.jsonConverter = jsonConverter;
-        this.interceptors = interceptors != null ? interceptors : Collections.emptyList();
-        this.mqttClient = null;
-        this.messageConverter = null;
-        this.mqttProperties = null;
-        this.reconnectManager = null;
-        this.retryExecutor = null;
-    }
-    
-    @Autowired(required = false)
-    public MqttTemplate(MqttClient mqttClient, List<MqttMessageInterceptor> interceptors, 
-                     MessageConverter messageConverter) {
-        this.mqttClient = mqttClient;
-        this.messageConverter = messageConverter;
-        this.interceptors = interceptors != null ? interceptors : Collections.emptyList();
-        this.mqttOutbound = null;
-        this.jsonConverter = (messageConverter instanceof JsonMessageConverter) ? 
-                            (JsonMessageConverter) messageConverter : null;
-        this.mqttProperties = null;
-        this.reconnectManager = null;
-        this.retryExecutor = null;
-    }
-    
-    @Autowired(required = false)
-    public MqttTemplate(MqttClient mqttClient, List<MqttMessageInterceptor> interceptors, 
-                     MessageConverter messageConverter, MqttProperties mqttProperties,
-                     MqttReconnectManager reconnectManager) {
-        this.mqttClient = mqttClient;
-        this.messageConverter = messageConverter;
-        this.interceptors = interceptors != null ? interceptors : Collections.emptyList();
-        this.mqttOutbound = null;
-        this.jsonConverter = (messageConverter instanceof JsonMessageConverter) ? 
-                            (JsonMessageConverter) messageConverter : null;
-        this.mqttProperties = mqttProperties;
-        this.reconnectManager = reconnectManager;
-        
-        // 创建重试线程池
-        ThreadFactory threadFactory = r -> {
-            Thread t = new Thread(r, "mqtt-retry-thread");
-            t.setDaemon(true);
-            return t;
-        };
-        
-        this.retryExecutor = Executors.newScheduledThreadPool(
-            Runtime.getRuntime().availableProcessors(), 
-            threadFactory
-        );
-        
-        log.info("MqttTemplate initialized with {} interceptors", this.interceptors.size());
-        
-        // 添加JVM关闭钩子,确保线程池正确关闭
-        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
-            shutdown();
-        }));
-    }
-
-    /**
-     * 发送字符串消息
-     *
-     * @param topic   主题
-     * @param payload 消息内容
-     * @return CompletableFuture<Void>
-     */
-    public CompletableFuture<Void> send(String topic, String payload) {
-        return send(topic, payload, mqttProperties != null ? mqttProperties.getDefaultQos() : 0, false);
-    }
-
-    /**
-     * 发送字符串消息(指定QoS和保留标志)
-     *
-     * @param topic   主题
-     * @param payload 消息内容
-     * @param qos     QoS级别
-     * @param retain  是否保留
-     * @return CompletableFuture<Void>
-     */
-    public CompletableFuture<Void> send(String topic, String payload, int qos, boolean retain) {
-        CompletableFuture<Void> future = new CompletableFuture<>();
-        totalMessagesSent.incrementAndGet();
-        
-        // 应用拦截器
-        String processedPayload = payload;
-        for (MqttMessageInterceptor interceptor : interceptors) {
-            try {
-                processedPayload = interceptor.beforePublish(topic, processedPayload);
-            } catch (Exception e) {
-                log.error("Error in message interceptor", e);
-                failedMessages.incrementAndGet();
-                future.completeExceptionally(e);
-                return future;
-            }
-        }
-        
-        try {
-            final String finalPayload = processedPayload;
-            if (mqttOutbound != null) {
-                Message<String> message = MessageBuilder
-                        .withPayload(finalPayload)
-                        .setHeader(MqttHeaders.TOPIC, topic)
-                        .setHeader(MqttHeaders.QOS, qos)
-                        .setHeader(MqttHeaders.RETAINED, retain)
-                        .build();
-                
-                mqttOutbound.handleMessage(message);
-                
-                // 通知拦截器
-                for (MqttMessageInterceptor interceptor : interceptors) {
-                    try {
-                        interceptor.afterPublish(topic, finalPayload);
-                    } catch (Exception e) {
-                        log.error("Error in message interceptor after publish", e);
-                    }
-                }
-                
-                future.complete(null);
-                log.debug("Sent message to topic: {}", topic);
-            } else if (mqttClient != null) {
-                publishWithRetry(topic, finalPayload.getBytes(), qos, retain, future, 0);
-                return future;
-            } else {
-                throw new IllegalStateException("No MQTT client or message handler available");
-            }
-        } catch (Exception e) {
-            failedMessages.incrementAndGet();
-            
-            // 使用异常处理器处理异常
-            if (e instanceof MqttException) {
-                final String finalPayload = processedPayload;
-                MqttExceptionHandler.handleException((MqttException) e, ex -> {
-                    if (mqttProperties != null && mqttProperties.isRetryOnPublishFailure() && 
-                        MqttExceptionHandler.isRecoverableByReconnect((MqttException) e)) {
-                        if (retryExecutor != null && !retryExecutor.isShutdown()) {
-                            log.info("Scheduling retry for message to topic: {}", topic);
-                            retryExecutor.schedule(() -> {
-                                retriedMessages.incrementAndGet();
-                                send(topic, finalPayload, qos, retain).thenAccept(v -> future.complete(null))
-                                    .exceptionally(t -> {
-                                        future.completeExceptionally(t);
-                                        return null;
-                                    });
-                            }, mqttProperties.getPublishRetryInterval(), TimeUnit.MILLISECONDS);
-                        } else {
-                            future.completeExceptionally(e);
-                        }
-                    } else {
-                        future.completeExceptionally(e);
-                    }
-                });
-            } else {
-                future.completeExceptionally(e);
-                log.error("Failed to send message to topic: {}", topic, e);
-            }
-        }
-        return future;
-    }
-    
-    /**
-     * 带重试机制的消息发布
-     * 
-     * @param topic 主题
-     * @param payload 消息内容
-     * @param qos QoS级别
-     * @param retain 是否保留
-     * @param future 完成回调
-     * @param retryCount 当前重试次数
-     */
-    private void publishWithRetry(String topic, byte[] payload, int qos, boolean retain, 
-                                CompletableFuture<Void> future, int retryCount) {
-        try {
-            MqttMessage message = new MqttMessage(payload);
-            message.setQos(qos);
-            message.setRetained(retain);
-            
-            if (!mqttClient.isConnected()) {
-                if (mqttProperties != null && mqttProperties.isAutomaticReconnect() && reconnectManager != null) {
-                    log.warn("MQTT client not connected, triggering reconnect before sending message");
-                    reconnectManager.triggerReconnect();
-                    
-                    // 如果启用了重试,则安排重试
-                    if (shouldRetry(retryCount)) {
-                        retriedMessages.incrementAndGet();
-                        scheduleRetry(topic, payload, qos, retain, future, retryCount + 1);
-                        return;
-                    } else {
-                        failedMessages.incrementAndGet();
-                        future.completeExceptionally(new MqttException(MqttException.REASON_CODE_CLIENT_NOT_CONNECTED));
-                        return;
-                    }
-                } else {
-                    failedMessages.incrementAndGet();
-                    future.completeExceptionally(new MqttException(MqttException.REASON_CODE_CLIENT_NOT_CONNECTED));
-                    return;
-                }
-            }
-            
-            // 应用拦截器
-            for (MqttMessageInterceptor interceptor : interceptors) {
-                if (!interceptor.preSend(topic, message)) {
-                    log.warn("Message sending cancelled by interceptor for topic: {}", topic);
-                    failedMessages.incrementAndGet();
-                    future.completeExceptionally(new IllegalStateException("Message sending cancelled by interceptor"));
-                    return;
-                }
-            }
-            
-            mqttClient.publish(topic, message);
-            future.complete(null);
-            log.debug("Successfully published message to topic: {}", topic);
-            
-            // 通知拦截器
-            for (MqttMessageInterceptor interceptor : interceptors) {
-                try {
-                    interceptor.postSend(topic, message);
-                    interceptor.afterPublish(topic, new String(payload));
-                } catch (Exception e) {
-                    log.error("Error in message interceptor after publish", e);
-                }
-            }
-        } catch (MqttException e) {
-            // 处理异常
-            String detailedError = MqttExceptionHandler.getDetailedErrorMessage(e);
-            log.error("Failed to publish message to topic {}: {}", topic, detailedError);
-            
-            // 如果是可恢复错误并且启用了重试,则安排重试
-            if (MqttExceptionHandler.isRecoverableByReconnect(e) && shouldRetry(retryCount)) {
-                log.info("Will retry publishing message to topic {} (attempt {}/{})", 
-                        topic, retryCount + 1, mqttProperties.getMaxPublishRetryAttempts());
-                retriedMessages.incrementAndGet();
-                scheduleRetry(topic, payload, qos, retain, future, retryCount + 1);
-            } else {
-                failedMessages.incrementAndGet();
-                future.completeExceptionally(e);
-                
-                // 提供解决方案建议
-                String recommendation = MqttExceptionHandler.getRecommendedAction(e);
-                log.info("Recommended action: {}", recommendation);
-            }
-        }
-    }
-    
-    /**
-     * 判断是否应该重试发送消息
-     * 
-     * @param retryCount 当前重试次数
-     * @return 是否应该重试
-     */
-    private boolean shouldRetry(int retryCount) {
-        return mqttProperties != null && 
-               mqttProperties.isRetryOnPublishFailure() && 
-               retryCount < mqttProperties.getMaxPublishRetryAttempts();
-    }
-    
-    /**
-     * 安排重试发送消息
-     * 
-     * @param topic 主题
-     * @param payload 消息内容
-     * @param qos QoS级别
-     * @param retain 是否保留
-     * @param future 完成回调
-     * @param retryCount 当前重试次数
-     */
-    private void scheduleRetry(String topic, byte[] payload, int qos, boolean retain, 
-                             CompletableFuture<Void> future, int retryCount) {
-        if (retryExecutor != null && !retryExecutor.isShutdown()) {
-            long delay = calculateRetryDelay(retryCount);
-            log.debug("Scheduling retry {} for topic {} in {} ms", retryCount, topic, delay);
-            
-            retryExecutor.schedule(
-                () -> publishWithRetry(topic, payload, qos, retain, future, retryCount),
-                delay,
-                TimeUnit.MILLISECONDS
-            );
-        } else {
-            future.completeExceptionally(new IllegalStateException("Retry executor is not available"));
-        }
-    }
-    
-    /**
-     * 计算重试延迟时间,使用指数退避算法
-     * 
-     * @param retryCount 当前重试次数
-     * @return 延迟时间(毫秒)
-     */
-    private long calculateRetryDelay(int retryCount) {
-        if (mqttProperties == null) {
-            return 1000; // 默认1秒
-        }
-        
-        long baseDelay = mqttProperties.getPublishRetryInterval();
-        double factor = Math.pow(mqttProperties.getReconnectBackoffMultiplier(), retryCount - 1);
-        long delay = (long)(baseDelay * factor);
-        
-        // 确保不超过最大重试间隔
-        return Math.min(delay, mqttProperties.getMaxReconnectInterval());
-    }
-
-    /**
-     * 发送JSON对象消息
-     *
-     * @param topic 主题
-     * @param payload 消息内容对象
-     * @return CompletableFuture<Void>
-     */
-    public CompletableFuture<Void> sendJson(String topic, Object payload) {
-        return sendJson(topic, payload, mqttProperties != null ? mqttProperties.getDefaultQos() : 0, false);
-    }
-
-    /**
-     * 发送JSON对象消息(指定QoS和保留标志)
-     *
-     * @param topic  主题
-     * @param payload 消息内容对象
-     * @param qos    QoS级别
-     * @param retain 是否保留
-     * @return CompletableFuture<Void>
-     */
-    public CompletableFuture<Void> sendJson(String topic, Object payload, int qos, boolean retain) {
-        CompletableFuture<Void> future = new CompletableFuture<>();
-        try {
-            if (jsonConverter != null) {
-                String json = jsonConverter.toJson(payload);
-                return send(topic, json, qos, retain);
-            } else if (messageConverter != null) {
-                MqttMessage message = messageConverter.toMessage(payload);
-                message.setQos(qos);
-                message.setRetained(retain);
-                
-                if (mqttClient != null) {
-                    publishWithRetry(topic, message.getPayload(), qos, retain, future, 0);
-                    return future;
-                } else {
-                    throw new IllegalStateException("No MQTT client available");
-                }
-            } else {
-                throw new IllegalStateException("No message converter available");
-            }
-        } catch (Exception e) {
-            failedMessages.incrementAndGet();
-            future.completeExceptionally(e);
-            log.error("Failed to convert object to JSON: {}", payload, e);
-            return future;
-        }
-    }
-
-    /**
-     * 同步发送消息
-     *
-     * @param topic   主题
-     * @param payload 消息内容
-     * @throws Exception 发送异常
-     */
-    public void sendSync(String topic, String payload) throws Exception {
-        sendSync(topic, payload, mqttProperties != null ? mqttProperties.getDefaultQos() : 0, false);
-    }
-
-    /**
-     * 同步发送消息(指定QoS和保留标志)
-     *
-     * @param topic   主题
-     * @param payload 消息内容
-     * @param qos     QoS级别
-     * @param retain  是否保留
-     * @throws Exception 发送异常
-     */
-    public void sendSync(String topic, String payload, int qos, boolean retain) throws Exception {
-        try {
-            send(topic, payload, qos, retain).get(
-                mqttProperties != null ? mqttProperties.getCompletionTimeout() : 5000, 
-                TimeUnit.MILLISECONDS
-            );
-        } catch (InterruptedException e) {
-            Thread.currentThread().interrupt();
-            throw new MqttException(MqttException.REASON_CODE_CLIENT_EXCEPTION, e);
-        } catch (ExecutionException e) {
-            if (e.getCause() instanceof MqttException) {
-                throw (MqttException) e.getCause();
-            } else {
-                throw new MqttException(MqttException.REASON_CODE_CLIENT_EXCEPTION, e.getCause());
-            }
-        } catch (TimeoutException e) {
-            throw new MqttException(MqttException.REASON_CODE_CLIENT_TIMEOUT, e);
-        }
-    }
-
-    /**
-     * 同步发送JSON对象消息
-     *
-     * @param topic 主题
-     * @param payload 消息内容对象
-     * @throws Exception 发送异常
-     */
-    public void sendJsonSync(String topic, Object payload) throws Exception {
-        sendJsonSync(topic, payload, mqttProperties != null ? mqttProperties.getDefaultQos() : 0, false);
-    }
-
-    /**
-     * 同步发送JSON对象消息(指定QoS和保留标志)
-     *
-     * @param topic  主题
-     * @param payload 消息内容对象
-     * @param qos    QoS级别
-     * @param retain 是否保留
-     * @throws Exception 发送异常
-     */
-    public void sendJsonSync(String topic, Object payload, int qos, boolean retain) throws Exception {
-        try {
-            sendJson(topic, payload, qos, retain).get(
-                mqttProperties != null ? mqttProperties.getCompletionTimeout() : 5000, 
-                TimeUnit.MILLISECONDS
-            );
-        } catch (InterruptedException e) {
-            Thread.currentThread().interrupt();
-            throw new MqttException(MqttException.REASON_CODE_CLIENT_EXCEPTION, e);
-        } catch (ExecutionException e) {
-            if (e.getCause() instanceof MqttException) {
-                throw (MqttException) e.getCause();
-            } else {
-                throw new MqttException(MqttException.REASON_CODE_CLIENT_EXCEPTION, e.getCause());
-            }
-        } catch (TimeoutException e) {
-            throw new MqttException(MqttException.REASON_CODE_CLIENT_TIMEOUT, e);
-        }
-    }
-    
-    /**
-     * 获取消息发送统计信息
-     * 
-     * @return 统计信息
-     */
-    public String getStatistics() {
-        int total = totalMessagesSent.get();
-        int failed = failedMessages.get();
-        int retried = retriedMessages.get();
-        int success = total - failed;
-        double successRate = total > 0 ? (double)success / total * 100 : 0;
-        
-        return String.format(
-            "Messages - Total: %d, Success: %d (%.2f%%), Failed: %d, Retried: %d",
-            total, success, successRate, failed, retried
-        );
-    }
-    
-    /**
-     * 重置统计信息
-     */
-    public void resetStatistics() {
-        totalMessagesSent.set(0);
-        failedMessages.set(0);
-        retriedMessages.set(0);
-    }
-    
-    /**
-     * 关闭资源
-     */
-    private void shutdown() {
-        if (retryExecutor != null && !retryExecutor.isShutdown()) {
-            log.info("Shutting down MQTT template retry executor");
-            retryExecutor.shutdown();
-            try {
-                if (!retryExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
-                    retryExecutor.shutdownNow();
-                }
-            } catch (InterruptedException e) {
-                retryExecutor.shutdownNow();
-                Thread.currentThread().interrupt();
-            }
-        }
-    }
-    
-    @Override
-    public void destroy() throws Exception {
-        shutdown();
-    }
-} 

BIN
mqtt-spring-boot-starter/src/main/resources/META-INF/spring.factories


+ 0 - 1
mqtt-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@@ -1 +0,0 @@
-cn.hfln.framework.mqtt.config.MqttAutoConfiguration 

BIN
mqtt-spring-boot-starter/src/main/resources/docs/MQTT批量操作使用指南.md


+ 0 - 61
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/batch/BatchResultTest.java

@@ -1,61 +0,0 @@
-package cn.hfln.framework.mqtt.batch;
-
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class BatchResultTest {
-    @Test
-    void testAddAndGetResults() {
-        BatchResult batch = new BatchResult();
-        BatchResult.OperationResult ok = BatchResult.success("t1", "p1");
-        BatchResult.OperationResult fail = BatchResult.failure("t2", "p2", "err", new RuntimeException("fail"));
-        batch.addResult(ok);
-        batch.addResult(fail);
-        List<BatchResult.OperationResult> results = batch.getResults();
-        assertEquals(2, results.size());
-        assertEquals("t1", results.get(0).getTopic());
-        assertEquals("p2", results.get(1).getPayload());
-        assertEquals("err", results.get(1).getErrorMessage());
-        assertEquals("fail", results.get(1).getException().getMessage());
-    }
-
-    @Test
-    void testAllSucceededAndCounts() {
-        BatchResult batch = new BatchResult();
-        batch.addResult(BatchResult.success("a", "x"));
-        batch.addResult(BatchResult.success("b", "y"));
-        assertTrue(batch.isAllSucceeded());
-        assertEquals(2, batch.getTotalCount());
-        assertEquals(2, batch.getSuccessCount());
-        assertEquals(0, batch.getFailureCount());
-        assertEquals(1.0, batch.getSuccessRate());
-    }
-
-    @Test
-    void testPartialSuccessAndFailedResults() {
-        BatchResult batch = new BatchResult();
-        batch.addResult(BatchResult.success("a", "x"));
-        batch.addResult(BatchResult.failure("b", "y", "bad", null));
-        assertFalse(batch.isAllSucceeded());
-        assertEquals(2, batch.getTotalCount());
-        assertEquals(1, batch.getSuccessCount());
-        assertEquals(1, batch.getFailureCount());
-        assertEquals(0.5, batch.getSuccessRate());
-        List<BatchResult.OperationResult> failed = batch.getFailedResults();
-        assertEquals(1, failed.size());
-        assertEquals("b", failed.get(0).getTopic());
-    }
-
-    @Test
-    void testOperationResultFields() {
-        BatchResult.OperationResult r = new BatchResult.OperationResult(false, "t", "p", "err", new Exception("ex"));
-        assertFalse(r.isSuccess());
-        assertEquals("t", r.getTopic());
-        assertEquals("p", r.getPayload());
-        assertEquals("err", r.getErrorMessage());
-        assertEquals("ex", r.getException().getMessage());
-    }
-} 

+ 0 - 82
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/batch/MqttBatchOperationsTest.java

@@ -1,82 +0,0 @@
-package cn.hfln.framework.mqtt.batch;
-
-import org.junit.jupiter.api.Test;
-import java.util.List;
-import java.util.Collections;
-import java.util.Arrays;
-import static org.junit.jupiter.api.Assertions.*;
-
-class MqttBatchOperationsTest {
-    // Java8兼容:补充Publisher接口定义(如主工程无定义)
-    public interface Publisher {
-        boolean publish(String topic, String payload);
-    }
-    // Java8兼容:补充静态batchPublish方法(如主工程无定义)
-    public static BatchResult batchPublish(List<String> topics, List<String> payloads, Publisher publisher) {
-        BatchResult result = new BatchResult();
-        int size = Math.min(topics.size(), payloads.size());
-        for (int i = 0; i < size; i++) {
-            String topic = topics.get(i);
-            String payload = payloads.get(i);
-            try {
-                boolean success = publisher.publish(topic, payload);
-                if (success) {
-                    result.addResult(BatchResult.success(topic, payload));
-                } else {
-                    result.addResult(BatchResult.failure(topic, payload, "fail", null));
-                }
-            } catch (Exception e) {
-                result.addResult(BatchResult.failure(topic, payload, e.getMessage(), e));
-            }
-        }
-        return result;
-    }
-    @Test
-    void testBatchPublishAllSuccess() {
-        List<String> topics = Arrays.asList("t1", "t2");
-        List<String> payloads = Arrays.asList("p1", "p2");
-        Publisher publisher = new Publisher() {
-            public boolean publish(String topic, String payload) { return true; }
-        };
-        BatchResult result = batchPublish(topics, payloads, publisher);
-        assertEquals(2, result.getTotalCount());
-        assertEquals(2, result.getSuccessCount());
-        assertTrue(result.isAllSucceeded());
-    }
-
-    @Test
-    void testBatchPublishPartialFail() {
-        List<String> topics = Arrays.asList("t1", "t2");
-        List<String> payloads = Arrays.asList("p1", "p2");
-        Publisher publisher = new Publisher() {
-            public boolean publish(String topic, String payload) { return topic.equals("t1"); }
-        };
-        BatchResult result = batchPublish(topics, payloads, publisher);
-        assertEquals(2, result.getTotalCount());
-        assertEquals(1, result.getSuccessCount());
-        assertFalse(result.isAllSucceeded());
-        assertEquals(1, result.getFailureCount());
-    }
-
-    @Test
-    void testBatchPublishWithException() {
-        List<String> topics = Arrays.asList("t1");
-        List<String> payloads = Arrays.asList("p1");
-        Publisher publisher = new Publisher() {
-            public boolean publish(String topic, String payload) { throw new RuntimeException("fail"); }
-        };
-        BatchResult result = batchPublish(topics, payloads, publisher);
-        assertEquals(1, result.getFailureCount());
-        assertFalse(result.isAllSucceeded());
-        assertEquals("fail", result.getResults().get(0).getException().getMessage());
-    }
-
-    @Test
-    void testBatchPublishEmpty() {
-        BatchResult result = batchPublish(Collections.emptyList(), Collections.emptyList(), new Publisher() {
-            public boolean publish(String t, String p) { return true; }
-        });
-        assertEquals(0, result.getTotalCount());
-        assertTrue(result.isAllSucceeded());
-    }
-} 

+ 0 - 10
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/batch/MqttBatchTemplateTest.java

@@ -1,10 +0,0 @@
-package cn.hfln.framework.mqtt.batch;
-
-import org.junit.jupiter.api.Test;
-
-class MqttBatchTemplateTest {
-    @Test
-    void placeholder() {
-        // 实现类为空,测试占位
-    }
-} 

+ 0 - 55
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/batch/impl/DelimiterMergeStrategyTest.java

@@ -1,55 +0,0 @@
-package cn.hfln.framework.mqtt.batch.impl;
-
-import org.junit.jupiter.api.Test;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class DelimiterMergeStrategyTest {
-    @Test
-    void testMerge_normal() {
-        DelimiterMergeStrategy strategy = new DelimiterMergeStrategy(",");
-        List<String> payloads = Arrays.asList("a", "b", "c");
-        String result = strategy.merge(payloads);
-        assertEquals("a,b,c", result);
-    }
-
-    @Test
-    void testMerge_emptyList() {
-        DelimiterMergeStrategy strategy = new DelimiterMergeStrategy("|");
-        String result = strategy.merge(Collections.emptyList());
-        assertEquals("", result);
-    }
-
-    @Test
-    void testMerge_nullList() {
-        DelimiterMergeStrategy strategy = new DelimiterMergeStrategy("|");
-        String result = strategy.merge(null);
-        assertEquals("", result);
-    }
-
-    @Test
-    void testMerge_singleElement() {
-        DelimiterMergeStrategy strategy = new DelimiterMergeStrategy("|");
-        String result = strategy.merge(Collections.singletonList("x"));
-        assertEquals("x", result);
-    }
-
-    @Test
-    void testGetNameAndDescription() {
-        DelimiterMergeStrategy strategy = new DelimiterMergeStrategy("-", "CustomName", "CustomDesc");
-        assertEquals("CustomName", strategy.getName());
-        assertEquals("CustomDesc", strategy.getDescription());
-        assertEquals("-", strategy.getDelimiter());
-    }
-
-    @Test
-    void testStaticFactories() {
-        assertEquals("\n", DelimiterMergeStrategy.newLine().getDelimiter());
-        assertEquals(",", DelimiterMergeStrategy.comma().getDelimiter());
-        assertEquals(";", DelimiterMergeStrategy.semicolon().getDelimiter());
-    }
-} 

+ 0 - 61
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/batch/impl/JsonArrayMergeStrategyTest.java

@@ -1,61 +0,0 @@
-package cn.hfln.framework.mqtt.batch.impl;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.junit.jupiter.api.Test;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class JsonArrayMergeStrategyTest {
-    @Test
-    void testMerge_normalJson() {
-        JsonArrayMergeStrategy strategy = new JsonArrayMergeStrategy();
-        List<String> payloads = Arrays.asList("{\"a\":1}", "{\"b\":2}");
-        String result = strategy.merge(payloads);
-        assertTrue(result.startsWith("["));
-        assertTrue(result.endsWith("]"));
-        assertTrue(result.contains("\"a\":1"));
-        assertTrue(result.contains("\"b\":2"));
-    }
-
-    @Test
-    void testMerge_invalidJson() {
-        JsonArrayMergeStrategy strategy = new JsonArrayMergeStrategy();
-        List<String> payloads = Arrays.asList("notjson", "{\"b\":2}");
-        String result = strategy.merge(payloads);
-        assertTrue(result.contains("notjson"));
-        assertTrue(result.contains("\"b\":2"));
-    }
-
-    @Test
-    void testMerge_emptyList() {
-        JsonArrayMergeStrategy strategy = new JsonArrayMergeStrategy();
-        String result = strategy.merge(Collections.emptyList());
-        assertEquals("[]", result);
-    }
-
-    @Test
-    void testMerge_nullList() {
-        JsonArrayMergeStrategy strategy = new JsonArrayMergeStrategy();
-        assertThrows(RuntimeException.class, () -> strategy.merge(null));
-    }
-
-    @Test
-    void testCustomObjectMapper() {
-        ObjectMapper mapper = new ObjectMapper();
-        JsonArrayMergeStrategy strategy = new JsonArrayMergeStrategy(mapper);
-        List<String> payloads = Arrays.asList("{\"x\":1}");
-        String result = strategy.merge(payloads);
-        assertTrue(result.contains("\"x\":1"));
-    }
-
-    @Test
-    void testGetNameAndDescription() {
-        JsonArrayMergeStrategy strategy = new JsonArrayMergeStrategy();
-        assertEquals("JsonArrayMerge", strategy.getName());
-        assertNotNull(strategy.getDescription());
-    }
-} 

+ 0 - 70
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/batch/impl/JsonSplitStrategyTest.java

@@ -1,70 +0,0 @@
-package cn.hfln.framework.mqtt.batch.impl;
-
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class JsonSplitStrategyTest {
-    @Test
-    void testSplit_array() {
-        JsonSplitStrategy strategy = new JsonSplitStrategy(2);
-        String json = "[1,2,3,4]";
-        List<String> chunks = strategy.split(json);
-        assertEquals(2, chunks.size());
-        assertTrue(chunks.get(0).contains("1"));
-        assertTrue(chunks.get(0).contains("2"));
-        assertTrue(chunks.get(1).contains("3"));
-        assertTrue(chunks.get(1).contains("4"));
-    }
-
-    @Test
-    void testSplit_objectWithArrayField() {
-        JsonSplitStrategy strategy = new JsonSplitStrategy(1, "arr");
-        String json = "{\"arr\":[10,20]}";
-        List<String> chunks = strategy.split(json);
-        assertEquals(2, chunks.size());
-        assertTrue(chunks.get(0).contains("10"));
-        assertFalse(chunks.get(0).contains("20"));
-        assertTrue(chunks.get(1).contains("20"));
-        assertFalse(chunks.get(1).contains("10"));
-    }
-
-    @Test
-    void testSplit_emptyPayload() {
-        JsonSplitStrategy strategy = new JsonSplitStrategy(2);
-        List<String> chunks = strategy.split("");
-        assertTrue(chunks.isEmpty());
-    }
-
-    @Test
-    void testSplit_nullPayload() {
-        JsonSplitStrategy strategy = new JsonSplitStrategy(2);
-        List<String> chunks = strategy.split(null);
-        assertTrue(chunks.isEmpty());
-    }
-
-    @Test
-    void testSplit_invalidJson() {
-        JsonSplitStrategy strategy = new JsonSplitStrategy(2);
-        String payload = "notjson";
-        List<String> chunks = strategy.split(payload);
-        assertEquals(1, chunks.size());
-        assertEquals(payload, chunks.get(0));
-    }
-
-    @Test
-    void testGetNameAndDescription() {
-        JsonSplitStrategy strategy = new JsonSplitStrategy(2, "arr");
-        assertEquals("JsonSplit", strategy.getName());
-        assertTrue(strategy.getDescription().contains("arr"));
-        assertEquals(2, strategy.getMaxItemsPerChunk());
-        assertEquals("arr", strategy.getArrayField());
-    }
-
-    @Test
-    void testInvalidMaxItemsPerChunk() {
-        assertThrows(IllegalArgumentException.class, () -> new JsonSplitStrategy(0));
-    }
-} 

+ 0 - 65
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/batch/impl/SizeLimitSplitStrategyTest.java

@@ -1,65 +0,0 @@
-package cn.hfln.framework.mqtt.batch.impl;
-
-import org.junit.jupiter.api.Test;
-
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class SizeLimitSplitStrategyTest {
-    @Test
-    void testSplit_normal() {
-        SizeLimitSplitStrategy strategy = new SizeLimitSplitStrategy(5);
-        String payload = "1234567890";
-        List<String> chunks = strategy.split(payload);
-        assertEquals(2, chunks.size());
-        assertEquals("12345", chunks.get(0));
-        assertEquals("67890", chunks.get(1));
-    }
-
-    @Test
-    void testSplit_exactSize() {
-        SizeLimitSplitStrategy strategy = new SizeLimitSplitStrategy(10);
-        String payload = "abcdefghij";
-        List<String> chunks = strategy.split(payload);
-        assertEquals(1, chunks.size());
-        assertEquals("abcdefghij", chunks.get(0));
-    }
-
-    @Test
-    void testSplit_emptyPayload() {
-        SizeLimitSplitStrategy strategy = new SizeLimitSplitStrategy(5);
-        List<String> chunks = strategy.split("");
-        assertTrue(chunks.isEmpty());
-    }
-
-    @Test
-    void testSplit_nullPayload() {
-        SizeLimitSplitStrategy strategy = new SizeLimitSplitStrategy(5);
-        List<String> chunks = strategy.split(null);
-        assertTrue(chunks.isEmpty());
-    }
-
-    @Test
-    void testSplit_utf8Boundary() {
-        SizeLimitSplitStrategy strategy = new SizeLimitSplitStrategy(4); // 4 bytes
-        String payload = "汉字a"; // 汉=3字节, 字=3字节, a=1字节
-        List<String> chunks = strategy.split(payload);
-        assertEquals(2, chunks.size());
-        assertTrue(chunks.get(0).length() < payload.length());
-    }
-
-    @Test
-    void testGetNameAndDescription() {
-        SizeLimitSplitStrategy strategy = new SizeLimitSplitStrategy(5, "TestName", "TestDesc");
-        assertEquals("TestName", strategy.getName());
-        assertEquals("TestDesc", strategy.getDescription());
-        assertEquals(5, strategy.getMaxPayloadSize());
-    }
-
-    @Test
-    void testInvalidMaxPayloadSize() {
-        assertThrows(IllegalArgumentException.class, () -> new SizeLimitSplitStrategy(0));
-    }
-} 

+ 0 - 57
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/config/MqttAutoConfigurationTest.java

@@ -1,57 +0,0 @@
-package cn.hfln.framework.mqtt.config;
-
-import cn.hfln.framework.mqtt.gateway.MqttGateway;
-import cn.hfln.framework.mqtt.template.MqttTemplate;
-import org.eclipse.paho.client.mqttv3.MqttClient;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.test.context.runner.ApplicationContextRunner;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.TaskScheduler;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class MqttAutoConfigurationTest {
-    private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
-            .withConfiguration(AutoConfigurations.of(MqttAutoConfiguration.class))
-            .withPropertyValues(
-                    "mqtt.broker=tcp://8.130.28.21:1883",
-                    "mqtt.username=testuser",
-                    "mqtt.password=testpass",
-                    "mqtt.keepalive=60",
-                    "mqtt.timeout=30"
-            );
-
-    @Test
-    void testMqttTemplateBeanCreated() {
-        contextRunner.withUserConfiguration(MockBeansConfig.class)
-                .run(context -> {
-                    assertThat(context).hasSingleBean(MqttTemplate.class);
-                });
-    }
-
-    @Test
-    void testMqttGatewayBeanCreated() {
-        contextRunner.withUserConfiguration(MockBeansConfig.class)
-                .run(context -> {
-                    assertThat(context).hasSingleBean(MqttGateway.class);
-                });
-    }
-
-    @Configuration
-    static class MockBeansConfig {
-        @Bean
-        public MqttClient mqttClient() {
-            return org.mockito.Mockito.mock(MqttClient.class);
-        }
-        @Bean
-        public cn.hfln.framework.mqtt.converter.MessageConverter messageConverter() {
-            return org.mockito.Mockito.mock(cn.hfln.framework.mqtt.converter.MessageConverter.class);
-        }
-        @Bean
-        public TaskScheduler taskScheduler() {
-            return org.mockito.Mockito.mock(TaskScheduler.class);
-        }
-    }
-} 

+ 0 - 56
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/config/MqttPropertiesTest.java

@@ -1,56 +0,0 @@
-package cn.hfln.framework.mqtt.config;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class MqttPropertiesTest {
-    @Test
-    void testDefaultValues() {
-        MqttProperties props = new MqttProperties();
-        assertEquals("tcp://localhost:1883", props.getBroker());
-        assertNull(props.getClientId());
-        assertNull(props.getUsername());
-        assertNull(props.getPassword());
-        assertEquals(1, props.getDefaultQos());
-        assertFalse(props.isDefaultRetained());
-        assertTrue(props.isAsync());
-        assertEquals(5000, props.getCompletionTimeout());
-        assertEquals(30, props.getTimeout());
-        assertEquals(60, props.getKeepalive());
-    }
-
-    @Test
-    void testSettersAndGetters() {
-        MqttProperties props = new MqttProperties();
-        props.setBroker("tcp://test:1883");
-        props.setClientId("cid");
-        props.setUsername("user");
-        props.setPassword("pass");
-        props.setDefaultQos(2);
-        props.setDefaultRetained(true);
-        props.setAsync(false);
-        props.setCompletionTimeout(10000);
-        props.setTimeout(99);
-        props.setKeepalive(77);
-        assertEquals("tcp://test:1883", props.getBroker());
-        assertEquals("cid", props.getClientId());
-        assertEquals("user", props.getUsername());
-        assertEquals("pass", props.getPassword());
-        assertEquals(2, props.getDefaultQos());
-        assertTrue(props.isDefaultRetained());
-        assertFalse(props.isAsync());
-        assertEquals(10000, props.getCompletionTimeout());
-        assertEquals(99, props.getTimeout());
-        assertEquals(77, props.getKeepalive());
-    }
-
-    @Test
-    void testEdgeCases() {
-        MqttProperties props = new MqttProperties();
-        props.setDefaultQos(-1);
-        assertEquals(-1, props.getDefaultQos());
-        props.setTimeout(0);
-        assertEquals(0, props.getTimeout());
-    }
-} 

+ 0 - 78
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/converter/JsonMessageConverterTest.java

@@ -1,78 +0,0 @@
-package cn.hfln.framework.mqtt.converter;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import org.eclipse.paho.client.mqttv3.MqttMessage;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class JsonMessageConverterTest {
-    private final JsonMessageConverter converter = new JsonMessageConverter();
-
-    static class TestObj {
-        public String name;
-        public int value;
-        public TestObj() {}
-        public TestObj(String name, int value) { this.name = name; this.value = value; }
-    }
-
-    @Test
-    void testToJson_object() throws Exception {
-        TestObj obj = new TestObj("foo", 42);
-        String json = converter.toJson(obj);
-        assertTrue(json.contains("\"name\":\"foo\"") && json.contains("\"value\":42"));
-    }
-
-    @Test
-    void testToJson_string() throws Exception {
-        String s = "abc";
-        assertEquals(s, converter.toJson(s));
-    }
-
-    @Test
-    void testToJson_null() throws Exception {
-        assertNull(converter.toJson(null));
-    }
-
-    @Test
-    void testFromJson_object() throws Exception {
-        String json = "{\"name\":\"bar\",\"value\":99}";
-        TestObj obj = converter.fromJson(json, TestObj.class);
-        assertEquals("bar", obj.name);
-        assertEquals(99, obj.value);
-    }
-
-    @Test
-    void testFromJson_nullOrEmpty() throws Exception {
-        assertNull(converter.fromJson(null, TestObj.class));
-        assertNull(converter.fromJson("", TestObj.class));
-    }
-
-    @Test
-    void testFromJson_invalid() {
-        assertThrows(JsonProcessingException.class, () -> converter.fromJson("not-json", TestObj.class));
-    }
-
-    @Test
-    void testToMessage_andFromMessage() {
-        TestObj obj = new TestObj("baz", 7);
-        MqttMessage msg = converter.toMessage(obj);
-        assertNotNull(msg);
-        TestObj result = converter.fromMessage(msg, TestObj.class);
-        assertEquals("baz", result.name);
-        assertEquals(7, result.value);
-    }
-
-    @Test
-    void testToMessage_null() {
-        MqttMessage msg = converter.toMessage(null);
-        assertNotNull(msg);
-        assertEquals("null", new String(msg.getPayload()));
-    }
-
-    @Test
-    void testFromMessage_invalidJson() {
-        MqttMessage msg = new MqttMessage("bad-json".getBytes());
-        assertThrows(RuntimeException.class, () -> converter.fromMessage(msg, TestObj.class));
-    }
-} 

+ 0 - 44
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/exception/MqttExceptionHandlerTest.java

@@ -1,44 +0,0 @@
-package cn.hfln.framework.mqtt.exception;
-
-import org.eclipse.paho.client.mqttv3.MqttException;
-import org.junit.jupiter.api.Test;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class MqttExceptionHandlerTest {
-    @Test
-    void testHandleException_withRecoverAction() {
-        AtomicBoolean called = new AtomicBoolean(false);
-        MqttException ex = new MqttException(1);
-        MqttExceptionHandler.handleException(ex, e -> called.set(true));
-        assertTrue(called.get());
-    }
-
-    @Test
-    void testHandleException_nullRecoverAction() {
-        MqttException ex = new MqttException(2);
-        assertDoesNotThrow(() -> MqttExceptionHandler.handleException(ex, null));
-    }
-
-    @Test
-    void testIsRecoverableByReconnect() {
-        MqttException ex = new MqttException(3);
-        assertFalse(MqttExceptionHandler.isRecoverableByReconnect(ex));
-    }
-
-    @Test
-    void testGetDetailedErrorMessage() {
-        MqttException ex = new MqttException(MqttException.REASON_CODE_CLIENT_EXCEPTION);
-        assertEquals(ex.getMessage(), MqttExceptionHandler.getDetailedErrorMessage(ex));
-        assertEquals("", MqttExceptionHandler.getDetailedErrorMessage(null));
-    }
-
-    @Test
-    void testGetRecommendedAction() {
-        MqttException ex = new MqttException(4);
-        assertEquals("请检查MQTT连接配置或网络状态", MqttExceptionHandler.getRecommendedAction(ex));
-        assertEquals("请检查MQTT连接配置或网络状态", MqttExceptionHandler.getRecommendedAction(null));
-    }
-} 

+ 0 - 155
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/gateway/DefaultMqttGatewayTest.java

@@ -1,155 +0,0 @@
-package cn.hfln.framework.mqtt.gateway;
-
-import cn.hfln.framework.mqtt.template.MqttTemplate;
-import org.eclipse.paho.client.mqttv3.MqttClient;
-import org.eclipse.paho.client.mqttv3.MqttException;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-import java.util.concurrent.CompletableFuture;
-
-class DefaultMqttGatewayTest {
-    @Mock
-    private MqttTemplate mqttTemplate;
-    @Mock
-    private MqttClient mqttClient;
-    private DefaultMqttGateway gateway;
-    private AutoCloseable mocks;
-
-    @BeforeEach
-    void setUp() {
-        mocks = MockitoAnnotations.openMocks(this);
-        gateway = new DefaultMqttGateway(mqttTemplate, mqttClient);
-    }
-
-    @Test
-    void testPublish_stringPayload() {
-        when(mqttTemplate.send(anyString(), anyString())).thenReturn(CompletableFuture.completedFuture(null));
-        gateway.publish("/topic", "msg");
-        verify(mqttTemplate, times(1)).send("/topic", "msg");
-    }
-
-    @Test
-    void testPublish_objectPayload() {
-        Object obj = new Object();
-        when(mqttTemplate.sendJson(anyString(), any())).thenReturn(CompletableFuture.completedFuture(null));
-        gateway.publish("/topic", obj);
-        verify(mqttTemplate, times(1)).sendJson("/topic", obj);
-    }
-
-    @Test
-    void testPublish_withQosAndRetain_string() {
-        when(mqttTemplate.send(anyString(), anyString(), anyInt(), anyBoolean())).thenReturn(CompletableFuture.completedFuture(null));
-        gateway.publish("/topic", "msg", 1, true);
-        verify(mqttTemplate, times(1)).send("/topic", "msg", 1, true);
-    }
-
-    @Test
-    void testPublish_withQosAndRetain_object() {
-        Object obj = new Object();
-        when(mqttTemplate.sendJson(anyString(), any(), anyInt(), anyBoolean())).thenReturn(CompletableFuture.completedFuture(null));
-        gateway.publish("/topic", obj, 2, false);
-        verify(mqttTemplate, times(1)).sendJson("/topic", obj, 2, false);
-    }
-
-    @Test
-    void testSendMessage() {
-        when(mqttTemplate.send(anyString(), anyString())).thenReturn(CompletableFuture.completedFuture(null));
-        gateway.sendMessage("/topic", "msg");
-        verify(mqttTemplate, times(1)).send("/topic", "msg");
-    }
-
-    @Test
-    void testSendMessage_withQosAndRetain() {
-        when(mqttTemplate.send(anyString(), anyString(), anyInt(), anyBoolean())).thenReturn(CompletableFuture.completedFuture(null));
-        gateway.sendMessage("/topic", "msg", 1, false);
-        verify(mqttTemplate, times(1)).send("/topic", "msg", 1, false);
-    }
-
-    @Test
-    void testPublishJson() {
-        Object obj = new Object();
-        when(mqttTemplate.sendJson(anyString(), any())).thenReturn(CompletableFuture.completedFuture(null));
-        gateway.publishJson("/topic", obj);
-        verify(mqttTemplate, times(1)).sendJson("/topic", obj);
-    }
-
-    @Test
-    void testPublishJson_withQosAndRetain() {
-        Object obj = new Object();
-        when(mqttTemplate.sendJson(anyString(), any(), anyInt(), anyBoolean())).thenReturn(CompletableFuture.completedFuture(null));
-        gateway.publishJson("/topic", obj, 2, true);
-        verify(mqttTemplate, times(1)).sendJson("/topic", obj, 2, true);
-    }
-
-    @Test
-    void testSendSync_string() throws Exception {
-        doNothing().when(mqttTemplate).sendSync(anyString(), any());
-        assertDoesNotThrow(() -> gateway.sendSync("/topic", "msg"));
-        verify(mqttTemplate, times(1)).sendSync("/topic", "msg");
-    }
-
-    @Test
-    void testSendSync_exception() throws Exception {
-        doThrow(new MqttException(1)).when(mqttTemplate).sendSync(anyString(), any());
-        assertThrows(MqttException.class, () -> gateway.sendSync("/topic", "msg"));
-        verify(mqttTemplate, times(1)).sendSync("/topic", "msg");
-    }
-
-    @Test
-    void testSubscribe() throws MqttException {
-        doNothing().when(mqttClient).subscribe(anyString(), anyInt());
-        gateway.subscribe("/topic", 1);
-        verify(mqttClient, times(1)).subscribe("/topic", 1);
-    }
-
-    @Test
-    void testSubscribe_exception() throws MqttException {
-        doThrow(new MqttException(1)).when(mqttClient).subscribe(anyString(), anyInt());
-        assertDoesNotThrow(() -> gateway.subscribe("/topic", 1)); // 异常被catch
-    }
-
-    @Test
-    void testUnsubscribe() throws MqttException {
-        doNothing().when(mqttClient).unsubscribe(anyString());
-        gateway.unsubscribe("/topic");
-        verify(mqttClient, times(1)).unsubscribe("/topic");
-    }
-
-    @Test
-    void testUnsubscribe_exception() throws MqttException {
-        doThrow(new MqttException(1)).when(mqttClient).unsubscribe(anyString());
-        assertDoesNotThrow(() -> gateway.unsubscribe("/topic")); // 异常被catch
-    }
-
-    @Test
-    void testIsConnected() {
-        when(mqttClient.isConnected()).thenReturn(true);
-        assertTrue(gateway.isConnected());
-        when(mqttClient.isConnected()).thenReturn(false);
-        assertFalse(gateway.isConnected());
-    }
-
-    @Test
-    void testDisconnect() throws MqttException {
-        doNothing().when(mqttClient).disconnect();
-        gateway.disconnect();
-        verify(mqttClient, times(1)).disconnect();
-    }
-
-    @Test
-    void testDisconnect_exception() throws MqttException {
-        doThrow(new MqttException(1)).when(mqttClient).disconnect();
-        assertDoesNotThrow(() -> gateway.disconnect()); // 异常被catch
-    }
-
-    @BeforeEach
-    void tearDown() throws Exception {
-        if (mocks != null) mocks.close();
-    }
-} 

+ 0 - 53
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/handler/MqttMessageHandlerTest.java

@@ -1,53 +0,0 @@
-package cn.hfln.framework.mqtt.handler;
-
-import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
-import org.eclipse.paho.client.mqttv3.MqttMessage;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class MqttMessageHandlerTest {
-    private MqttMessageHandler handler;
-
-    @BeforeEach
-    void setUp() {
-        handler = new MqttMessageHandler();
-    }
-
-    @Test
-    void testConnectionLost() {
-        // 不抛异常即可
-        assertDoesNotThrow(() -> handler.connectionLost(new RuntimeException("lost")));
-    }
-
-    @Test
-    void testMessageArrived() {
-        // 不抛异常即可
-        assertDoesNotThrow(() -> handler.messageArrived("test/topic", new MqttMessage("payload".getBytes())));
-    }
-
-    @Test
-    void testDeliveryComplete() {
-        // 不抛异常即可
-        IMqttDeliveryToken token = new IMqttDeliveryToken() {
-            @Override public void waitForCompletion() {}
-            @Override public void waitForCompletion(long timeout) {}
-            @Override public boolean isComplete() { return true; }
-            @Override public MqttMessage getMessage() { return null; }
-            @Override public int getMessageId() { return 0; }
-            @Override public String[] getTopics() { return new String[0]; }
-            @Override public void setUserContext(Object userContext) {}
-            @Override public Object getUserContext() { return null; }
-            @Override public void setActionCallback(org.eclipse.paho.client.mqttv3.IMqttActionListener listener) {}
-            @Override public org.eclipse.paho.client.mqttv3.IMqttActionListener getActionCallback() { return null; }
-            // 下面为IMqttToken接口方法
-            @Override public int[] getGrantedQos() { return new int[0]; }
-            @Override public org.eclipse.paho.client.mqttv3.MqttException getException() { return null; }
-            @Override public org.eclipse.paho.client.mqttv3.IMqttAsyncClient getClient() { return null; }
-            @Override public org.eclipse.paho.client.mqttv3.internal.wire.MqttWireMessage getResponse() { return null; }
-            @Override public boolean getSessionPresent() { return false; }
-        };
-        assertDoesNotThrow(() -> handler.deliveryComplete(token));
-    }
-} 

+ 0 - 68
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/handler/MqttMessageRouterTest.java

@@ -1,68 +0,0 @@
-package cn.hfln.framework.mqtt.handler;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
-
-import java.util.regex.Pattern;
-
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-class MqttMessageRouterTest {
-    private MqttMessageRouter router;
-    private MqttTopicHandler handler;
-
-    @BeforeEach
-    void setUp() {
-        router = new MqttMessageRouter();
-        handler = mock(MqttTopicHandler.class);
-    }
-
-    @Test
-    void testRegisterAndRoute() throws Exception {
-        router.register("test/.*", handler);
-        String topic = "test/abc";
-        String payload = "msg";
-        assertTrue(router.route(topic, payload));
-        verify(handler, times(1)).handle(topic, payload);
-    }
-
-    @Test
-    void testRegisterPatternAndRoute() throws Exception {
-        Pattern pattern = Pattern.compile("foo/\\d+");
-        router.register(pattern, handler);
-        String topic = "foo/123";
-        assertTrue(router.route(topic, "bar"));
-        verify(handler, times(1)).handle(topic, "bar");
-    }
-
-    @Test
-    void testRouteNoMatch() throws Exception {
-        router.register("abc/.*", handler);
-        assertFalse(router.route("def/123", "payload"));
-        verify(handler, never()).handle(anyString(), anyString());
-    }
-
-    @Test
-    void testRouteHandlerThrows() throws Exception {
-        router.register("err/.*", handler);
-        doThrow(new RuntimeException("fail")).when(handler).handle(anyString(), anyString());
-        assertFalse(router.route("err/1", "x")); // 异常被catch但未算handled
-        verify(handler, times(1)).handle("err/1", "x");
-    }
-
-    @Test
-    void testUnregister() {
-        router.register("abc/.*", handler);
-        router.unregister("abc/.*");
-        assertFalse(router.route("abc/1", "x"));
-    }
-
-    @Test
-    void testClear() {
-        router.register("abc/.*", handler);
-        router.clear();
-        assertFalse(router.route("abc/1", "x"));
-    }
-} 

+ 0 - 114
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/handler/MqttSubscribeProcessorTest.java

@@ -1,114 +0,0 @@
-package cn.hfln.framework.mqtt.handler;
-
-import cn.hfln.framework.mqtt.annotation.MqttSubscribe;
-import org.eclipse.paho.client.mqttv3.MqttClient;
-import org.eclipse.paho.client.mqttv3.MqttException;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.springframework.context.ApplicationContext;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.Map;
-
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-class MqttSubscribeProcessorTest {
-    @Mock
-    private MqttClient mqttClient;
-    @Mock
-    private ApplicationContext applicationContext;
-
-    private MqttSubscribeProcessor processor;
-
-    @BeforeEach
-    void setUp() throws Exception {
-        MockitoAnnotations.openMocks(this);
-        processor = new MqttSubscribeProcessor();
-        // 反射注入私有依赖
-        Field mqttClientField = MqttSubscribeProcessor.class.getDeclaredField("mqttClient");
-        mqttClientField.setAccessible(true);
-        mqttClientField.set(processor, mqttClient);
-        Field appCtxField = MqttSubscribeProcessor.class.getDeclaredField("applicationContext");
-        appCtxField.setAccessible(true);
-        appCtxField.set(processor, applicationContext);
-    }
-
-    @Test
-    void testPostProcessAfterInitialization_withMethodAnnotation_success() {
-        try {
-            when(mqttClient.isConnected()).thenReturn(true);
-            TestMethodClass bean = new TestMethodClass();
-            Object result = processor.postProcessAfterInitialization(bean, "testMethodClass");
-            assertSame(bean, result);
-            verify(mqttClient).subscribe("/test/method", 2);
-            Method method = processor.getMethodForTopic("/test/method");
-            assertNotNull(method);
-            assertEquals("onMessage", method.getName());
-        } catch (Exception e) {
-            fail("Exception in method annotation test: " + e.getMessage());
-        }
-    }
-
-    @Test
-    void testPostProcessAfterInitialization_mqttNotConnected() {
-        try {
-            when(mqttClient.isConnected()).thenReturn(false);
-            TestMethodClass bean = new TestMethodClass();
-            processor.postProcessAfterInitialization(bean, "testMethodClass");
-            verify(mqttClient, never()).subscribe(anyString(), anyInt());
-            assertNull(processor.getMethodForTopic("/test/method"));
-        } catch (Exception e) {
-            fail("Exception in mqttNotConnected test: " + e.getMessage());
-        }
-    }
-
-    @Test
-    void testProcessMqttSubscribe_mqttException() {
-        try {
-            when(mqttClient.isConnected()).thenReturn(true);
-            doThrow(new MqttException(1)).when(mqttClient).subscribe(anyString(), anyInt());
-            TestMethodClass bean = new TestMethodClass();
-            processor.postProcessAfterInitialization(bean, "testMethodClass");
-            // Should not throw, just log error
-            assertNull(processor.getMethodForTopic("/test/method"));
-        } catch (Exception e) {
-            fail("Exception in mqttException test: " + e.getMessage());
-        }
-    }
-
-    @Test
-    void testGetMethodForTopic_exactAndWildcard() {
-        when(mqttClient.isConnected()).thenReturn(true);
-        TestMethodClass bean = new TestMethodClass();
-        processor.postProcessAfterInitialization(bean, "testMethodClass");
-        // exact
-        assertNotNull(processor.getMethodForTopic("/test/method"));
-        // wildcard
-        try {
-            Field topicMapField = MqttSubscribeProcessor.class.getDeclaredField("topicMethodMap");
-            topicMapField.setAccessible(true);
-            @SuppressWarnings("unchecked")
-            Map<String, Method> topicMap = (Map<String, Method>) topicMapField.get(processor);
-            topicMap.put("/wildcard/+", TestMethodClass.class.getMethod("onMessage", String.class));
-            assertNotNull(processor.getMethodForTopic("/wildcard/abc"));
-            topicMap.put("/wildcard/#", TestMethodClass.class.getMethod("onMessage", String.class));
-            assertNotNull(processor.getMethodForTopic("/wildcard/abc/def"));
-        } catch (Exception e) {
-            fail("Exception in wildcard topic test: " + e.getMessage());
-        }
-    }
-
-    @Test
-    void testGetMethodForTopic_noMatch() {
-        assertNull(processor.getMethodForTopic("/not/exist"));
-    }
-
-    static class TestMethodClass {
-        @MqttSubscribe(topic = "/test/method", qos = 2)
-        public void onMessage(String msg) {}
-    }
-} 

+ 0 - 153
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/handler/MqttSubscriberProcessorTest.java

@@ -1,153 +0,0 @@
-package cn.hfln.framework.mqtt.handler;
-
-import cn.hfln.framework.mqtt.annotation.MqttSubscriber;
-import org.eclipse.paho.client.mqttv3.MqttClient;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.springframework.context.ApplicationContext;
-import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
-import org.springframework.messaging.Message;
-import org.springframework.messaging.MessageHeaders;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-class MqttSubscriberProcessorTest {
-    @Mock
-    private MqttPahoMessageDrivenChannelAdapter mqttInbound;
-    @Mock
-    private MqttClient mqttClient;
-    @Mock
-    private ApplicationContext applicationContext;
-
-    private MqttSubscriberProcessor processor;
-
-    @BeforeEach
-    void setUp() throws Exception {
-        MockitoAnnotations.openMocks(this);
-        processor = new MqttSubscriberProcessor(mqttInbound, mqttClient);
-        Field ctxField = MqttSubscriberProcessor.class.getDeclaredField("applicationContext");
-        ctxField.setAccessible(true);
-        ctxField.set(processor, applicationContext);
-    }
-
-    @Test
-    void testAfterSingletonsInstantiated_registersSubscribers() {
-        when(applicationContext.getBeanDefinitionNames()).thenReturn(new String[]{"testBean"});
-        when(applicationContext.getBean("testBean")).thenReturn(new TestSubscriber());
-        processor.afterSingletonsInstantiated();
-        // 验证topic注册
-        verify(mqttInbound).addTopic("/test/topic", 1);
-    }
-
-    @Test
-    void testProcessMessage_exactMatch() throws Exception {
-        // 注册订阅方法
-        TestSubscriber bean = new TestSubscriber();
-        Method method = TestSubscriber.class.getMethod("handle", String.class);
-        MqttSubscriber annotation = method.getAnnotation(MqttSubscriber.class);
-        Object subscriberMethod = createSubscriberMethod(bean, method, annotation);
-        putTopicSubscriber("/test/topic", subscriberMethod);
-        // 构造消息
-        Message<String> message = mock(Message.class);
-        Map<String, Object> headers1 = new HashMap<>();
-        headers1.put("mqtt_receivedTopic", "/test/topic");
-        when(message.getHeaders()).thenReturn(new MessageHeaders(headers1));
-        when(message.getPayload()).thenReturn("payload");
-        // 调用
-        invokeProcessMessage(message);
-        assertEquals("payload", bean.lastMsg);
-    }
-
-    @Test
-    void testProcessMessage_wildcardMatch() throws Exception {
-        TestSubscriber bean = new TestSubscriber();
-        Method method = TestSubscriber.class.getMethod("handle", String.class);
-        MqttSubscriber annotation = method.getAnnotation(MqttSubscriber.class);
-        Object subscriberMethod = createSubscriberMethod(bean, method, annotation);
-        putTopicSubscriber("/test/+", subscriberMethod);
-        Message<String> message = mock(Message.class);
-        Map<String, Object> headers2 = new HashMap<>();
-        headers2.put("mqtt_receivedTopic", "/test/abc");
-        when(message.getHeaders()).thenReturn(new MessageHeaders(headers2));
-        when(message.getPayload()).thenReturn("wild");
-        invokeProcessMessage(message);
-        assertEquals("wild", bean.lastMsg);
-    }
-
-    @Test
-    void testProcessMessage_noSubscriber() {
-        Message<String> message = mock(Message.class);
-        Map<String, Object> headers3 = new HashMap<>();
-        headers3.put("mqtt_receivedTopic", "/not/exist");
-        when(message.getHeaders()).thenReturn(new MessageHeaders(headers3));
-        when(message.getPayload()).thenReturn("none");
-        // 不抛异常
-        invokeProcessMessage(message);
-    }
-
-    @Test
-    void testProcessMessage_nullTopic() {
-        Message<String> message = mock(Message.class);
-        when(message.getHeaders()).thenReturn(new MessageHeaders(new HashMap<>()));
-        when(message.getPayload()).thenReturn("none");
-        // 不抛异常
-        invokeProcessMessage(message);
-    }
-
-    @Test
-    void testInvokeSubscriberMethod_invalidParamCount() throws Exception {
-        TestInvalidSubscriber bean = new TestInvalidSubscriber();
-        Method method = TestInvalidSubscriber.class.getMethod("invalid", String.class, String.class, String.class);
-        MqttSubscriber annotation = method.getAnnotation(MqttSubscriber.class);
-        Method regMethod = MqttSubscriberProcessor.class.getDeclaredMethod("registerSubscriberMethod", Object.class, Method.class, MqttSubscriber.class);
-        regMethod.setAccessible(true);
-        regMethod.invoke(processor, bean, method, annotation);
-        // 不会注册
-        Field mapField = MqttSubscriberProcessor.class.getDeclaredField("topicSubscriberMap");
-        mapField.setAccessible(true);
-        Map<String, ?> map = (Map<String, ?>) mapField.get(processor);
-        assertFalse(map.containsKey("/invalid/topic"));
-    }
-
-    // 工具方法:反射注入topicSubscriberMap
-    private void putTopicSubscriber(String topic, Object subscriberMethod) throws Exception {
-        Field mapField = MqttSubscriberProcessor.class.getDeclaredField("topicSubscriberMap");
-        mapField.setAccessible(true);
-        Map<String, Object> map = (Map<String, Object>) mapField.get(processor);
-        map.put(topic, subscriberMethod);
-    }
-    // 工具方法:反射创建SubscriberMethod
-    private Object createSubscriberMethod(Object bean, Method method, MqttSubscriber annotation) throws Exception {
-        Class<?> smClass = Class.forName("cn.hfln.framework.mqtt.handler.MqttSubscriberProcessor$SubscriberMethod");
-        return smClass.getConstructor(Object.class, Method.class, MqttSubscriber.class)
-                .newInstance(bean, method, annotation);
-    }
-    // 工具方法:反射调用processMessage
-    private void invokeProcessMessage(Message<?> message) {
-        try {
-            Method m = MqttSubscriberProcessor.class.getDeclaredMethod("processMessage", Message.class);
-            m.setAccessible(true);
-            m.invoke(processor, message);
-        } catch (Exception e) {
-            fail("Exception in processMessage: " + e.getMessage());
-        }
-    }
-
-    static class TestSubscriber {
-        String lastMsg;
-        @MqttSubscriber(topic = "/test/topic", qos = 1)
-        public void handle(String msg) { lastMsg = msg; }
-    }
-    static class TestInvalidSubscriber {
-        @MqttSubscriber(topic = "/invalid/topic", qos = 1)
-        public void invalid(String a, String b, String c) {}
-    }
-} 

+ 0 - 35
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/handler/MqttTopicHandlerTest.java

@@ -1,35 +0,0 @@
-package cn.hfln.framework.mqtt.handler;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class MqttTopicHandlerTest {
-    static class SimpleHandler implements MqttTopicHandler {
-        String lastTopic;
-        String lastPayload;
-        boolean throwError = false;
-        @Override
-        public void handle(String topic, String payload) throws Exception {
-            if (throwError) throw new Exception("fail");
-            lastTopic = topic;
-            lastPayload = payload;
-        }
-    }
-
-    @Test
-    void testHandleNormal() throws Exception {
-        SimpleHandler handler = new SimpleHandler();
-        handler.handle("topic/1", "payload");
-        assertEquals("topic/1", handler.lastTopic);
-        assertEquals("payload", handler.lastPayload);
-    }
-
-    @Test
-    void testHandleThrowsException() {
-        SimpleHandler handler = new SimpleHandler();
-        handler.throwError = true;
-        Exception ex = assertThrows(Exception.class, () -> handler.handle("t", "p"));
-        assertEquals("fail", ex.getMessage());
-    }
-} 

+ 0 - 27
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/listener/DefaultMqttConnectionListenerTest.java

@@ -1,27 +0,0 @@
-package cn.hfln.framework.mqtt.listener;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class DefaultMqttConnectionListenerTest {
-    @Test
-    void testOnConnected() {
-        DefaultMqttConnectionListener listener = new DefaultMqttConnectionListener();
-        assertDoesNotThrow(listener::onConnected);
-    }
-
-    @Test
-    void testOnDisconnected() {
-        DefaultMqttConnectionListener listener = new DefaultMqttConnectionListener();
-        Throwable cause = new RuntimeException("disconnect");
-        assertDoesNotThrow(() -> listener.onDisconnected(cause));
-    }
-
-    @Test
-    void testOnConnectionFailed() {
-        DefaultMqttConnectionListener listener = new DefaultMqttConnectionListener();
-        Throwable cause = new RuntimeException("fail");
-        assertDoesNotThrow(() -> listener.onConnectionFailed(cause));
-    }
-} 

+ 0 - 31
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/listener/DefaultMqttMessageListenerTest.java

@@ -1,31 +0,0 @@
-package cn.hfln.framework.mqtt.listener;
-
-import org.eclipse.paho.client.mqttv3.MqttMessage;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class DefaultMqttMessageListenerTest {
-    @Test
-    void testOnMessage_normal() {
-        DefaultMqttMessageListener listener = new DefaultMqttMessageListener();
-        String topic = "test/topic";
-        MqttMessage message = new MqttMessage("hello".getBytes());
-        assertDoesNotThrow(() -> listener.onMessage(topic, message));
-    }
-
-    @Test
-    void testOnMessage_emptyPayload() {
-        DefaultMqttMessageListener listener = new DefaultMqttMessageListener();
-        String topic = "test/topic";
-        MqttMessage message = new MqttMessage(new byte[0]);
-        assertDoesNotThrow(() -> listener.onMessage(topic, message));
-    }
-
-    @Test
-    void testOnMessage_nullTopic() {
-        DefaultMqttMessageListener listener = new DefaultMqttMessageListener();
-        MqttMessage message = new MqttMessage("data".getBytes());
-        assertDoesNotThrow(() -> listener.onMessage(null, message));
-    }
-} 

+ 0 - 70
mqtt-spring-boot-starter/src/test/java/cn/hfln/framework/mqtt/template/MqttTemplateTest.java

@@ -1,70 +0,0 @@
-package cn.hfln.framework.mqtt.template;
-
-import cn.hfln.framework.mqtt.converter.JsonMessageConverter;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
-
-import java.util.concurrent.CompletableFuture;
-
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-class MqttTemplateTest {
-    @Mock
-    private MqttPahoMessageHandler mqttOutbound;
-    @Mock
-    private JsonMessageConverter jsonMessageConverter;
-    private MqttTemplate mqttTemplate;
-    private AutoCloseable mocks;
-
-    @BeforeEach
-    void setUp() {
-        mocks = MockitoAnnotations.openMocks(this);
-        mqttTemplate = new MqttTemplate(mqttOutbound, jsonMessageConverter);
-    }
-
-    @Test
-    void testSend_success() {
-        String topic = "/test/topic";
-        String payload = "hello";
-        doNothing().when(mqttOutbound).handleMessage(any());
-        CompletableFuture<Void> future = mqttTemplate.send(topic, payload);
-        assertDoesNotThrow(future::join);
-        verify(mqttOutbound, times(1)).handleMessage(any());
-    }
-
-    @Test
-    void testSend_nullTopic() {
-        String payload = "hello";
-        CompletableFuture<Void> future = mqttTemplate.send(null, payload);
-        assertDoesNotThrow(future::join);
-        verify(mqttOutbound, times(1)).handleMessage(any());
-    }
-
-    @Test
-    void testSend_nullPayload() {
-        String topic = "/test/topic";
-        assertThrows(Exception.class, () -> mqttTemplate.send(topic, null).join());
-    }
-
-    @Test
-    void testSend_exceptionFromOutbound() {
-        String topic = "/test/topic";
-        String payload = "fail";
-        doThrow(new RuntimeException("fail outbound")).when(mqttOutbound).handleMessage(any());
-        CompletableFuture<Void> future = mqttTemplate.send(topic, payload);
-        assertThrows(Exception.class, future::join);
-    }
-
-    @AfterEach
-    void tearDown() throws Exception {
-        if (mocks != null) {
-            mocks.close();
-        }
-    }
-} 

+ 1 - 1
pom.xml

@@ -33,7 +33,7 @@
         <module>device-service-infrastructure</module>
         <module>device-service-server</module>
         <module>device-service-common</module>
-        <module>mqtt-spring-boot-starter</module>
+<!--        <module>mqtt-spring-boot-starter</module>-->
     </modules>
     <dependencies>
         <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->