WEBSOCKET_INTEGRATION.md 9.0 KB

WebSocket 集成说明

概述

在将商户店铺入住申请接口从 alien-store 迁移到 alien-store-platform 的过程中,需要集成 WebSocket 消息推送功能,用于实时通知商户申请已受理。

当前状态

已完成

  • ✅ 在 StoreManageServiceImpl.sendApplicationNotice() 中添加了 WebSocket 消息推送的调用逻辑
  • ✅ 创建了 WebSocketUtil 工具类作为占位实现
  • ✅ 保存通知消息到数据库(LifeNotice 表)
  • ✅ 构建了符合规范的 WebSocketVo 对象

待完成

  • ⚠️ WebSocket 实际消息推送功能(当前仅记录日志)

问题说明

架构限制

alien-store 模块中的 WebSocketProcess 类位于 shop.alien.store.config 包下,alien-store-platform 模块无法直接引用:

// alien-store 中的 WebSocketProcess
@ServerEndpoint(value = "/socket/{sendId}")
public class WebSocketProcess {
    public void sendMessage(String id, String message) throws Exception {
        // WebSocket 发送逻辑
    }
}

技术原因

  • 模块隔离alien-store-platformalien-store 是独立的微服务模块
  • 依赖管理alien-store-platform 的 pom.xml 中未引入 alien-store 依赖
  • 架构设计:微服务间不应直接引用对方的实现类

解决方案

方案 1:将 WebSocketProcess 移到共享模块(推荐)⭐

步骤:

  1. WebSocketProcess.javaalien-store 移动到 alien-config 模块
  2. 修改包路径为 shop.alien.config.websocket.WebSocketProcess
  3. alien-storealien-store-platformpom.xml 中都引用 alien-config 依赖(已存在)
  4. 更新 WebSocketUtil 使用共享的 WebSocketProcess

优点:

  • ✅ 代码复用,统一管理
  • ✅ 符合微服务架构设计原则
  • ✅ 两个服务都可以使用相同的 WebSocket 功能

缺点:

  • ❌ 需要重构 alien-store 中的现有代码
  • ❌ 可能影响到其他使用 WebSocket 的功能

实现示例:

// alien-config/src/main/java/shop/alien/config/websocket/WebSocketProcess.java
package shop.alien.config.websocket;

@Slf4j
@Component
@ServerEndpoint(value = "/socket/{sendId}")
public class WebSocketProcess {
    // ... 原有实现保持不变
}

// alien-store-platform/.../WebSocketUtil.java
package shop.alien.storeplatform.util;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import shop.alien.config.websocket.WebSocketProcess;

@Component
@RequiredArgsConstructor
public class WebSocketUtil {
    private final WebSocketProcess webSocketProcess;
    
    public void sendMessage(String receiverId, String message) {
        webSocketProcess.sendMessage(receiverId, message);
    }
}

方案 2:通过消息队列异步推送

步骤:

  1. 引入消息队列(RabbitMQ 或 Kafka)
  2. alien-store-platform 发送消息到 MQ
  3. alien-store 消费 MQ 消息并通过 WebSocket 推送

优点:

  • ✅ 服务解耦,符合微服务架构
  • ✅ 异步处理,不影响业务主流程
  • ✅ 支持消息持久化和重试机制

缺点:

  • ❌ 增加系统复杂度
  • ❌ 需要引入和维护消息队列中间件
  • ❌ 消息推送存在延迟

实现示例:

// alien-store-platform - 生产者
@Component
@RequiredArgsConstructor
public class WebSocketUtil {
    private final RabbitTemplate rabbitTemplate;
    
    public void sendMessage(String receiverId, String message) {
        WebSocketMessage msg = new WebSocketMessage(receiverId, message);
        rabbitTemplate.convertAndSend("websocket.exchange", "websocket.route", msg);
    }
}

// alien-store - 消费者
@Component
@RequiredArgsConstructor
public class WebSocketMessageConsumer {
    private final WebSocketProcess webSocketProcess;
    
    @RabbitListener(queues = "websocket.queue")
    public void handleMessage(WebSocketMessage msg) {
        webSocketProcess.sendMessage(msg.getReceiverId(), msg.getMessage());
    }
}

方案 3:通过 Feign 调用 REST 接口

步骤:

  1. alien-store 中创建 WebSocket 发送的 REST 接口
  2. alien-api 中定义 Feign 客户端接口
  3. alien-store-platform 通过 Feign 调用

优点:

  • ✅ 实现简单直接
  • ✅ 无需额外中间件
  • ✅ 易于调试和监控

缺点:

  • ❌ 增加 HTTP 调用开销
  • ❌ 存在网络延迟
  • ❌ 需要处理服务间调用失败的情况

实现示例:

// alien-store - 提供 REST 接口
@RestController
@RequestMapping("/internal/websocket")
public class WebSocketInternalController {
    @Autowired
    private WebSocketProcess webSocketProcess;
    
    @PostMapping("/sendMessage")
    public R sendMessage(@RequestParam String receiverId, @RequestParam String message) {
        webSocketProcess.sendMessage(receiverId, message);
        return R.success();
    }
}

// alien-api - Feign 客户端
@FeignClient(name = "alien-store", path = "/internal/websocket")
public interface WebSocketFeignClient {
    @PostMapping("/sendMessage")
    R sendMessage(@RequestParam("receiverId") String receiverId, 
                  @RequestParam("message") String message);
}

// alien-store-platform - 使用 Feign
@Component
@RequiredArgsConstructor
public class WebSocketUtil {
    private final WebSocketFeignClient webSocketFeignClient;
    
    public void sendMessage(String receiverId, String message) {
        webSocketFeignClient.sendMessage(receiverId, message);
    }
}

当前实现

WebSocketUtil(占位实现)

alien-store-platform/src/main/java/shop/alien/storeplatform/util/WebSocketUtil.java

@Slf4j
@Component
public class WebSocketUtil {
    public void sendMessage(String receiverId, String message) {
        // TODO: 实现WebSocket消息推送
        log.info("WebSocketUtil.sendMessage - [占位实现] 准备发送消息: receiverId={}, message={}", 
                receiverId, message);
        log.warn("WebSocketUtil.sendMessage - WebSocket功能未完全实现,消息未实际推送");
    }
}

调用位置

alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StoreManageServiceImpl.java

private void sendApplicationNotice(String userAccount) {
    // ... 构建通知消息
    
    // 1. 保存通知消息到数据库
    lifeNoticeMapper.insert(lifeNotice);
    
    // 2. 通过 WebSocket 实时推送消息
    WebSocketVo websocketVo = new WebSocketVo();
    websocketVo.setSenderId("system");
    websocketVo.setReceiverId(receiverId);
    websocketVo.setCategory("notice");
    websocketVo.setNoticeType("1");
    websocketVo.setIsRead(0);
    websocketVo.setText(JSONObject.from(lifeNotice).toJSONString());
    
    try {
        webSocketUtil.sendMessage(receiverId, JSONObject.from(websocketVo).toJSONString());
        log.info("WebSocket消息推送成功: receiverId={}", receiverId);
    } catch (Exception e) {
        log.error("WebSocket消息推送失败: {}", e.getMessage(), e);
    }
}

推荐实施步骤

短期方案(快速上线)

采用 方案 3:Feign 调用

  1. alien-store 中添加 WebSocket 发送的内部接口
  2. alien-api 中定义 Feign 客户端
  3. 更新 alien-store-platformWebSocketUtil
  4. 测试验证

预计时间: 1-2 小时

长期方案(架构优化)

采用 方案 1:共享模块

  1. 创建 alien-configwebsocket 子包
  2. 迁移 WebSocketProcess 到共享模块
  3. 更新 alien-storealien-store-platform 的引用
  4. 全面回归测试

预计时间: 4-8 小时

测试验证

功能测试

  1. 调用 /storeManage/applyStore 接口提交店铺入住申请
  2. 检查数据库 life_notice 表是否插入通知记录
  3. 检查 WebSocket 客户端是否收到实时消息
  4. 验证消息内容格式和字段完整性

日志验证

[INFO ] WebSocketUtil.sendMessage - [占位实现] 准备发送消息: receiverId=store_13800138000
[WARN ] WebSocketUtil.sendMessage - WebSocket功能未完全实现,消息未实际推送

相关文件

  • alien-store-platform/src/main/java/shop/alien/storeplatform/util/WebSocketUtil.java
  • alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StoreManageServiceImpl.java
  • alien-store/src/main/java/shop/alien/store/config/WebSocketProcess.java
  • alien-entity/src/main/java/shop/alien/entity/store/vo/WebSocketVo.java
  • alien-entity/src/main/java/shop/alien/entity/store/LifeNotice.java

注意事项

  1. ⚠️ 通知已保存到数据库:即使 WebSocket 推送失败,通知消息也已保存到 life_notice 表,用户可以在消息列表中查看
  2. ⚠️ 异常处理:当前实现已捕获 WebSocket 推送异常,不会影响主业务流程
  3. ⚠️ 日志记录:占位实现会记录警告日志,便于后续排查和优化
  4. ⚠️ 兼容性:选择方案 1 时需要确保不影响 alien-store 现有的 WebSocket 功能

更新记录

  • 2025-01-xx:初始创建,添加 WebSocket 占位实现
  • 待定:实施正式的 WebSocket 推送方案