Files
java-template/docs/message_integration_implementation_guide.md
T
BrunoGaoandClaude e402548e45 fix: 修复customer_id字段缺失问题,完成数据库schema同步
数据库修复:
- t_user_health_data_daily: 添加customer_id字段(租户ID)
- t_user_health_data_weekly: 添加customer_id字段(租户ID)

ljwx-boot同步更新:
- TUserHealthDataDailyMapper.xml: 添加customer_id字段映射
- TUserHealthDataWeeklyMapper.xml: 添加customer_id字段映射

其他改进:
- 告警规则缓存优化
- Redis缓存性能提升
- 健康数据处理性能优化
- 添加完整的文档和工具脚本

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
2025-09-10 13:49:59 +08:00

28 KiB

消息数据流集成实施指南

基于对现有代码的详细分析,本文档提供具体的实施步骤和代码改动建议。

一、实施概览

目标

  • 完整打通 ljwx-admin/ljwx-bigscreen → ljwx-boot → ljwx-phone → ljwx-watch 的消息数据流
  • 实现实时消息推送和状态跟踪
  • 支持消息生命周期管理和统计分析
  • 保持现有API和数据结构的向后兼容

技术栈

  • ljwx-boot: Java Spring Boot + MyBatis Plus + Redis
  • ljwx-bigscreen: Python Flask + SQLAlchemy + Redis
  • ljwx-phone: Flutter + Dart + Redis Client
  • ljwx-watch: HarmonyOS 4.0 + Java

二、数据库扩展(阶段一)

2.1 SQL脚本

-- 扩展 t_device_message 表
ALTER TABLE t_device_message 
ADD COLUMN title VARCHAR(500) COMMENT '消息标题',
ADD COLUMN priority INTEGER DEFAULT 3 COMMENT '优先级1-5',
ADD COLUMN urgency VARCHAR(20) DEFAULT 'medium' COMMENT '紧急程度',
ADD COLUMN channels JSON COMMENT '分发渠道',
ADD COLUMN require_ack BOOLEAN DEFAULT false COMMENT '需要确认',
ADD COLUMN expiry_time DATETIME COMMENT '过期时间',
ADD COLUMN metadata JSON COMMENT '元数据';

-- 扩展 t_device_message_detail 表
ALTER TABLE t_device_message_detail
ADD COLUMN distribution_id VARCHAR(255) COMMENT '分发ID',
ADD COLUMN target_type VARCHAR(50) COMMENT '目标类型',
ADD COLUMN target_id VARCHAR(255) COMMENT '目标ID', 
ADD COLUMN delivery_status VARCHAR(50) COMMENT '分发状态',
ADD COLUMN channel VARCHAR(50) COMMENT '分发渠道',
ADD COLUMN response_time INTEGER COMMENT '响应时间秒',
ADD COLUMN acknowledge_time DATETIME COMMENT '确认时间',
ADD COLUMN delivery_details JSON COMMENT '分发详情';

-- 创建索引优化查询
CREATE INDEX idx_message_device_sn ON t_device_message(device_sn);
CREATE INDEX idx_message_org_id ON t_device_message(org_id);
CREATE INDEX idx_message_type_status ON t_device_message(message_type, message_status);
CREATE INDEX idx_detail_message_id ON t_device_message_detail(message_id);
CREATE INDEX idx_detail_device_sn ON t_device_message_detail(device_sn);
CREATE INDEX idx_detail_delivery_status ON t_device_message_detail(delivery_status);

2.2 ljwx-boot实体类更新

// TDeviceMessage.java 新增字段
@TableName("t_device_message")
public class TDeviceMessage extends BaseEntity {
    // 现有字段...
    
    private String title;
    private Integer priority;
    private String urgency;
    private String channels;  // JSON字符串
    private Boolean requireAck;
    private LocalDateTime expiryTime;
    private String metadata;  // JSON字符串
}

// TDeviceMessageDetail.java 新增字段  
@TableName("t_device_message_detail")
public class TDeviceMessageDetail extends BaseEntity {
    // 现有字段...
    
    private String distributionId;
    private String targetType;
    private String targetId;
    private String deliveryStatus;
    private String channel;
    private Integer responseTime;
    private LocalDateTime acknowledgeTime;
    private String deliveryDetails;  // JSON字符串
}

2.3 ljwx-bigscreen模型更新

# models.py 扩展
class DeviceMessage(db.Model):
    __tablename__ = 't_device_message'
    # 现有字段...
    
    title = db.Column(db.String(500), nullable=True)
    priority = db.Column(db.Integer, default=3)
    urgency = db.Column(db.String(20), default='medium')
    channels = db.Column(db.JSON, nullable=True)
    require_ack = db.Column(db.Boolean, default=False)
    expiry_time = db.Column(db.DateTime, nullable=True)
    metadata = db.Column(db.JSON, nullable=True)

class DeviceMessageDetail(db.Model):
    __tablename__ = 't_device_message_detail'
    # 现有字段...
    
    distribution_id = db.Column(db.String(255), nullable=True)
    target_type = db.Column(db.String(50), nullable=True)
    target_id = db.Column(db.String(255), nullable=True)
    delivery_status = db.Column(db.String(50), nullable=True)
    channel = db.Column(db.String(50), nullable=True)
    response_time = db.Column(db.Integer, nullable=True)
    acknowledge_time = db.Column(db.DateTime, nullable=True)
    delivery_details = db.Column(db.JSON, nullable=True)

三、后端服务增强(阶段二)

3.1 ljwx-boot Redis配置

// RedisConfig.java
@Configuration
public class RedisConfig {
    
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        template.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
        return template;
    }
    
    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory factory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(factory);
        return container;
    }
}

3.2 ljwx-boot增强消息服务

// EnhancedMessageService.java
@Service
@Slf4j
public class EnhancedMessageService {
    
    @Autowired
    private ITDeviceMessageService messageService;
    
    @Autowired
    private ITDeviceMessageDetailService detailService;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    /**
     * 统一消息发布接口
     */
    @Transactional
    public Long publishMessage(MessagePublishRequest request) {
        try {
            // 1. 创建主消息
            TDeviceMessage message = buildMainMessage(request);
            messageService.save(message);
            
            // 2. 创建分发详情
            List<TDeviceMessageDetail> details = buildMessageDetails(message, request.getTargets());
            detailService.saveBatch(details);
            
            // 3. 发布到Redis
            publishToRedis(message, details);
            
            log.info("✅ 消息发布成功: messageId={}, 目标数量={}", message.getId(), details.size());
            return message.getId();
            
        } catch (Exception e) {
            log.error("❌ 消息发布失败: {}", e.getMessage(), e);
            throw new RuntimeException("消息发布失败", e);
        }
    }
    
    /**
     * 批量更新消息状态
     */
    public void updateMessageStatus(Long messageId, String status, List<String> deviceSns) {
        // 更新详情状态
        LambdaUpdateWrapper<TDeviceMessageDetail> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(TDeviceMessageDetail::getMessageId, messageId)
               .in(TDeviceMessageDetail::getDeviceSn, deviceSns)
               .set(TDeviceMessageDetail::getDeliveryStatus, status)
               .set(TDeviceMessageDetail::getAcknowledgeTime, LocalDateTime.now());
        
        detailService.update(wrapper);
        
        // 检查是否需要更新主消息状态
        updateMainMessageStatus(messageId);
        
        // 发布状态更新事件
        Map<String, Object> statusEvent = new HashMap<>();
        statusEvent.put("messageId", messageId);
        statusEvent.put("status", status);
        statusEvent.put("deviceSns", deviceSns);
        statusEvent.put("timestamp", System.currentTimeMillis());
        
        redisTemplate.convertAndSend("message:status:updates", statusEvent);
    }
    
    private void publishToRedis(TDeviceMessage message, List<TDeviceMessageDetail> details) {
        for (TDeviceMessageDetail detail : details) {
            Map<String, Object> payload = new HashMap<>();
            payload.put("messageId", message.getId());
            payload.put("deviceSn", detail.getDeviceSn());
            payload.put("messageType", message.getMessageType());
            payload.put("title", message.getTitle());
            payload.put("content", message.getMessage());
            payload.put("priority", message.getPriority());
            payload.put("urgency", message.getUrgency());
            payload.put("sentTime", message.getSentTime());
            payload.put("requireAck", message.getRequireAck());
            payload.put("channel", detail.getChannel());
            
            String channel = "message:device:" + detail.getDeviceSn();
            redisTemplate.convertAndSend(channel, payload);
        }
    }
}

3.3 ljwx-bigscreen增强跟踪

# enhanced_message_service.py
class EnhancedMessageService:
    
    def __init__(self):
        self.redis_client = redis.Redis(host='localhost', port=6379, db=0)
    
    def create_tracked_message(self, message_data):
        """创建带跟踪的消息"""
        try:
            # 创建主消息
            message = DeviceMessage(
                device_sn=message_data.get('device_sn'),
                message=message_data.get('content'),
                title=message_data.get('title'),
                message_type=message_data.get('message_type', 'notification'),
                sender_type=message_data.get('sender_type', 'admin'),
                receiver_type=message_data.get('receiver_type', 'device'),
                priority=message_data.get('priority', 3),
                urgency=message_data.get('urgency', 'medium'),
                channels=json.dumps(message_data.get('channels', ['message'])),
                require_ack=message_data.get('require_ack', False),
                org_id=message_data.get('org_id'),
                user_id=message_data.get('user_id'),
                customer_id=message_data.get('customer_id', 0),
                metadata=json.dumps(message_data.get('metadata', {}))
            )
            
            db.session.add(message)
            db.session.flush()  # 获取ID
            
            # 创建分发记录
            targets = message_data.get('targets', [])
            details = []
            
            for target in targets:
                detail = DeviceMessageDetail(
                    message_id=message.id,
                    device_sn=target.get('device_sn'),
                    message=message.message,
                    message_type=message.message_type,
                    sender_type=message.sender_type,
                    receiver_type=message.receiver_type,
                    customer_id=message.customer_id,
                    org_id=message.org_id,
                    distribution_id=f"dist_{message.id}_{target.get('device_sn')}",
                    target_type=target.get('target_type', 'device'),
                    target_id=target.get('target_id', target.get('device_sn')),
                    delivery_status='pending',
                    channel=target.get('channel', 'message')
                )
                details.append(detail)
                db.session.add(detail)
            
            db.session.commit()
            
            # 发布到Redis
            self._publish_message_created(message, details)
            
            return message
            
        except Exception as e:
            db.session.rollback()
            print(f"❌ 创建跟踪消息失败: {e}")
            return None
    
    def _publish_message_created(self, message, details):
        """发布消息创建事件"""
        for detail in details:
            payload = {
                'messageId': message.id,
                'deviceSn': detail.device_sn,
                'messageType': message.message_type,
                'title': message.title,
                'content': message.message,
                'priority': message.priority,
                'urgency': message.urgency,
                'sentTime': message.sent_time.isoformat() if message.sent_time else None,
                'requireAck': message.require_ack,
                'channel': detail.channel
            }
            
            channel = f'message:device:{detail.device_sn}'
            self.redis_client.publish(channel, json.dumps(payload))
    
    def get_message_statistics(self, org_id, start_date=None, end_date=None):
        """获取消息统计"""
        query = DeviceMessage.query.filter_by(org_id=str(org_id))
        
        if start_date:
            query = query.filter(DeviceMessage.create_time >= start_date)
        if end_date:
            query = query.filter(DeviceMessage.create_time <= end_date)
        
        messages = query.all()
        
        # 统计计算
        stats = {
            'totalMessages': len(messages),
            'messageTypes': {},
            'completionStats': {
                'totalTargets': 0,
                'delivered': 0,
                'acknowledged': 0,
                'pending': 0,
                'failed': 0
            }
        }
        
        # 消息类型统计
        for message in messages:
            msg_type = message.message_type
            stats['messageTypes'][msg_type] = stats['messageTypes'].get(msg_type, 0) + 1
            
            # 获取详情统计
            details = DeviceMessageDetail.query.filter_by(message_id=message.id).all()
            stats['completionStats']['totalTargets'] += len(details)
            
            for detail in details:
                status = detail.delivery_status or 'pending'
                if status in stats['completionStats']:
                    stats['completionStats'][status] += 1
        
        # 计算完成率
        total = stats['completionStats']['totalTargets']
        if total > 0:
            acknowledged = stats['completionStats']['acknowledged']
            stats['completionStats']['completionRate'] = round(acknowledged / total * 100, 2)
        else:
            stats['completionStats']['completionRate'] = 0.0
        
        return stats

# 新增API端点
@app.route('/api/enhanced/message/create', methods=['POST'])
def create_enhanced_message():
    """创建增强消息"""
    data = request.get_json()
    
    service = EnhancedMessageService()
    message = service.create_tracked_message(data)
    
    if message:
        return jsonify({
            'success': True,
            'messageId': message.id,
            'message': '消息创建成功'
        })
    else:
        return jsonify({
            'success': False,
            'error': '消息创建失败'
        }), 500

@app.route('/api/enhanced/message/stats/<int:org_id>', methods=['GET'])
def get_enhanced_message_stats(org_id):
    """获取增强消息统计"""
    start_date = request.args.get('startDate')
    end_date = request.args.get('endDate')
    
    service = EnhancedMessageService()
    stats = service.get_message_statistics(org_id, start_date, end_date)
    
    return jsonify({
        'success': True,
        'data': stats
    })

四、移动端实时化(阶段三)

4.1 ljwx-phone Redis集成

// lib/services/redis_service.dart
import 'dart:convert';
import 'dart:async';

class RedisService {
  static RedisService? _instance;
  StreamController<Map<String, dynamic>>? _messageController;
  
  static RedisService get instance {
    _instance ??= RedisService._internal();
    return _instance!;
  }
  
  RedisService._internal();
  
  Stream<Map<String, dynamic>> get messageStream {
    _messageController ??= StreamController<Map<String, dynamic>>.broadcast();
    return _messageController!.stream;
  }
  
  Future<void> subscribeToMessages(String deviceSn) async {
    try {
      // 订阅设备消息通道
      String channel = 'message:device:$deviceSn';
      
      // 这里需要集成实际的Redis客户端
      // 示例使用WebSocket或HTTP长连接模拟
      await _connectToRedis(channel);
      
    } catch (e) {
      print('Redis订阅失败: $e');
    }
  }
  
  Future<void> _connectToRedis(String channel) async {
    // 实际实现中可以使用redis_client包或者WebSocket
    // 这里提供框架结构
  }
  
  void publishAcknowledgment(Map<String, dynamic> ackData) {
    try {
      String channel = 'message:acknowledgments';
      String payload = jsonEncode(ackData);
      
      // 发布确认事件
      _publishToRedis(channel, payload);
      
    } catch (e) {
      print('发布确认失败: $e');
    }
  }
  
  void _publishToRedis(String channel, String payload) {
    // 实际Redis发布实现
  }
}
// lib/services/enhanced_message_service.dart
class EnhancedMessageService extends ApiService {
  StreamSubscription<Map<String, dynamic>>? _redisSubscription;
  final StreamController<Message> _localMessageController = StreamController<Message>.broadcast();
  
  Stream<Message> get localMessageStream => _localMessageController.stream;
  
  @override
  void initState() {
    super.initState();
    _initializeRedisSubscription();
    _startPeriodicSync(); // 保持现有定时同步作为备用
  }
  
  void _initializeRedisSubscription() async {
    try {
      String deviceSn = AppConfig.instance.deviceSn;
      await RedisService.instance.subscribeToMessages(deviceSn);
      
      _redisSubscription = RedisService.instance.messageStream.listen((data) {
        _handleRedisMessage(data);
      });
      
    } catch (e) {
      print('初始化Redis订阅失败: $e');
    }
  }
  
  void _handleRedisMessage(Map<String, dynamic> data) {
    try {
      // 转换为Message对象
      Message message = Message(
        id: data['messageId'].toString(),
        title: data['title'] ?? '',
        content: data['content'] ?? '',
        createTime: data['sentTime'] ?? DateTime.now().toIso8601String(),
        department: '', // 从设备信息获取
        messageStatus: '1', // 未读状态
        messageType: data['messageType'] ?? 'notification',
      );
      
      // 保存到本地
      _saveMessageLocally(message);
      
      // 通知UI更新
      _localMessageController.add(message);
      
      // 转发给手表(如果蓝牙连接)
      if (BluetoothService().isConnected) {
        BluetoothService().forwardMessageToWatch(data);
      }
      
    } catch (e) {
      print('处理Redis消息失败: $e');
    }
  }
  
  @override
  Future<bool> markMessageAsRead(String deviceSn, {
    DateTime? receivedTime,
    String? messageId,
    Map<String, dynamic>? originalMessage
  }) async {
    
    // 调用现有API
    final success = await super.markMessageAsRead(
      deviceSn,
      receivedTime: receivedTime,
      messageId: messageId,
      originalMessage: originalMessage
    );
    
    if (success && messageId != null) {
      // 发布确认事件到Redis
      RedisService.instance.publishAcknowledgment({
        'type': 'message_acknowledged',
        'messageId': messageId,
        'deviceSn': deviceSn,
        'acknowledgeTime': (receivedTime ?? DateTime.now()).toIso8601String(),
        'responseTime': _calculateResponseTime(originalMessage),
        'source': 'phone',
        'platform': 'ljwx-phone'
      });
    }
    
    return success;
  }
  
  int _calculateResponseTime(Map<String, dynamic>? originalMessage) {
    if (originalMessage == null || originalMessage['sentTime'] == null) {
      return 0;
    }
    
    try {
      DateTime sentTime = DateTime.parse(originalMessage['sentTime']);
      DateTime now = DateTime.now();
      return now.difference(sentTime).inSeconds;
    } catch (e) {
      return 0;
    }
  }
  
  void _saveMessageLocally(Message message) {
    // 保存到本地数据库或缓存
    // 可以使用sqflite或hive
  }
}

4.2 ljwx-phone UI更新

// lib/screens/enhanced_messages_screen.dart
class EnhancedMessagesScreen extends StatefulWidget {
  @override
  _EnhancedMessagesScreenState createState() => _EnhancedMessagesScreenState();
}

class _EnhancedMessagesScreenState extends State<EnhancedMessagesScreen> {
  late EnhancedMessageService _messageService;
  StreamSubscription<Message>? _messageSubscription;
  
  @override
  void initState() {
    super.initState();
    _messageService = EnhancedMessageService();
    _messageService.initState();
    
    // 监听实时消息
    _messageSubscription = _messageService.localMessageStream.listen((message) {
      setState(() {
        // 更新UI
      });
      
      // 显示通知
      _showMessageNotification(message);
    });
  }
  
  void _showMessageNotification(Message message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text('新消息: ${message.title}'),
        action: SnackBarAction(
          label: '查看',
          onPressed: () => _openMessageDetail(message),
        ),
      ),
    );
  }
  
  @override
  void dispose() {
    _messageSubscription?.cancel();
    super.dispose();
  }
}

五、手表端优化(阶段四)

5.1 ljwx-watch增强确认机制

// HttpService.java 增强确认
public void sendEnhancedMessageAcknowledgment(JSONObject originalMessage) {
    try {
        String messageId = originalMessage.getString("message_id");
        
        // 构建增强确认数据
        JSONObject ackData = new JSONObject();
        ackData.put("type", "message_acknowledgment");
        ackData.put("messageId", messageId);
        ackData.put("deviceSn", dataManager.getDeviceSn());
        ackData.put("acknowledgeTime", getCurrentISOTimestamp());
        ackData.put("responseTime", calculateResponseTime(originalMessage));
        ackData.put("channel", "http");
        ackData.put("source", "watch");
        ackData.put("platform", "ljwx-watch");
        
        // 设备信息
        JSONObject deviceInfo = new JSONObject();
        deviceInfo.put("watchModel", "HarmonyOS Watch");
        deviceInfo.put("osVersion", "4.0");
        deviceInfo.put("appVersion", getAppVersion());
        deviceInfo.put("batteryLevel", getBatteryLevel());
        ackData.put("deviceInfo", deviceInfo);
        
        // 用户行为信息
        ackData.put("userAction", "acknowledged");
        ackData.put("interactionMethod", "touch");
        
        // 复制原消息关键字段
        copyMessageFields(ackData, originalMessage);
        
        // 发送确认
        String ackUrl = dataManager.getFetchMessageUrl() + "/acknowledge";
        JSONObject response = postDataToServer(ackUrl, ackData);
        
        if (response != null && response.getBoolean("success")) {
            Log.i(TAG, "✅ 增强消息确认发送成功: " + messageId);
            showConfirmationFeedback(); // 显示确认反馈
        } else {
            Log.w(TAG, "⚠️ 增强消息确认发送失败,缓存重试: " + messageId);
            cacheAcknowledgmentForRetry(ackData);
        }
        
    } catch (Exception e) {
        Log.e(TAG, "❌ 增强消息确认异常: " + e.getMessage());
    }
}

private int calculateResponseTime(JSONObject originalMessage) {
    try {
        String sentTimeStr = originalMessage.getString("sent_time");
        // 解析发送时间并计算差值
        long sentTime = parseDateToTimestamp(sentTimeStr);
        long currentTime = System.currentTimeMillis();
        return (int) ((currentTime - sentTime) / 1000);
    } catch (Exception e) {
        Log.w(TAG, "无法计算响应时间: " + e.getMessage());
        return -1;
    }
}

private void showConfirmationFeedback() {
    // 显示确认成功的视觉反馈
    vibrate(100); // 震动反馈
    showToast("消息已确认");
}

private void copyMessageFields(JSONObject ackData, JSONObject originalMessage) {
    String[] fieldsToCoopy = {
        "message", "message_type", "sent_time", "user_id", 
        "user_name", "department_id", "department_name", "is_public"
    };
    
    for (String field : fieldsToCoopy) {
        if (originalMessage.has(field)) {
            try {
                ackData.put(field, originalMessage.get(field));
            } catch (JSONException e) {
                Log.w(TAG, "复制字段失败: " + field);
            }
        }
    }
}

六、部署和测试

6.1 环境配置

# docker-compose.yml 添加Redis
version: '3.8'
services:
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data

  ljwx-boot:
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379

volumes:
  redis_data:

6.2 测试脚本

# test_message_flow.py
import requests
import json
import time

class MessageFlowTester:
    
    def __init__(self):
        self.bigscreen_url = "http://localhost:5000"
        self.boot_url = "http://localhost:8080"
    
    def test_complete_flow(self):
        """测试完整消息流"""
        
        # 1. 在大屏创建消息
        message_data = {
            "title": "测试消息",
            "content": "这是一条测试消息",
            "message_type": "notification",
            "sender_type": "admin",
            "priority": 3,
            "urgency": "medium",
            "channels": ["message", "push"],
            "require_ack": True,
            "targets": [
                {
                    "device_sn": "TEST_DEVICE_001",
                    "target_type": "device",
                    "channel": "message"
                }
            ],
            "org_id": "1",
            "customer_id": 1
        }
        
        response = requests.post(
            f"{self.bigscreen_url}/api/enhanced/message/create",
            json=message_data
        )
        
        assert response.status_code == 200
        result = response.json()
        assert result['success'] == True
        
        message_id = result['messageId']
        print(f"✅ 消息创建成功: {message_id}")
        
        # 2. 等待消息传播
        time.sleep(2)
        
        # 3. 检查消息状态
        stats_response = requests.get(
            f"{self.bigscreen_url}/api/enhanced/message/stats/1"
        )
        
        assert stats_response.status_code == 200
        stats = stats_response.json()
        print(f"✅ 消息统计: {stats['data']}")
        
        return message_id
    
    def test_acknowledgment(self, message_id):
        """测试消息确认"""
        
        ack_data = {
            "messageId": message_id,
            "deviceSn": "TEST_DEVICE_001",
            "acknowledgeTime": "2025-09-10T10:00:00Z",
            "responseTime": 30,
            "source": "phone"
        }
        
        # 模拟手机端确认
        response = requests.post(
            f"{self.boot_url}/api/message/acknowledge",
            json=ack_data
        )
        
        print(f"✅ 消息确认测试完成")

if __name__ == "__main__":
    tester = MessageFlowTester()
    message_id = tester.test_complete_flow()
    tester.test_acknowledgment(message_id)
    print("🎉 完整流程测试成功!")

七、监控和维护

7.1 性能监控

// MessagePerformanceMonitor.java
@Component
public class MessagePerformanceMonitor {
    
    private final MeterRegistry meterRegistry;
    
    public MessagePerformanceMonitor(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }
    
    public void recordMessageCreated(String messageType) {
        meterRegistry.counter("message.created", "type", messageType).increment();
    }
    
    public void recordMessageDelivered(String channel, long deliveryTime) {
        meterRegistry.timer("message.delivery.time", "channel", channel)
            .record(deliveryTime, TimeUnit.MILLISECONDS);
    }
    
    public void recordMessageAcknowledged(String source, long responseTime) {
        meterRegistry.timer("message.response.time", "source", source)
            .record(responseTime, TimeUnit.SECONDS);
    }
}

7.2 日志配置

# logback-spring.xml
<configuration>
    <appender name="MESSAGE_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/message.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/message.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>100MB</maxFileSize>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    
    <logger name="com.ljwx.modules.health.service.EnhancedMessageService" level="INFO" additivity="false">
        <appender-ref ref="MESSAGE_FILE"/>
    </logger>
</configuration>

八、总结

通过以上实施方案,可以实现:

  1. 完整数据流打通: 四端消息传递无缝连接
  2. 实时状态同步: Redis驱动的实时更新
  3. 全面跟踪能力: 从创建到确认的完整监控
  4. 向后兼容性: 保持现有API不变
  5. 可监控性: 完善的日志和性能指标

实施周期约为5-6周,每个阶段独立部署,风险可控。