docs: 迁移 spring-ai 通用文档到 rui-docs

从 docs-local 迁移以下文档:

- backend/guides/: AI开发环境配置、Nacos配置、GitNexus指南、OpenCode工作流等

- backend/templates/: Superpowers设计模板、计划模板、审查清单

- backend/config-templates/: 应用配置模板、Nacos配置

- backend/design/: 数据库表结构规划

- backend/specs/: 项目文档治理、MQ统一推送设计

- backend/: 代码分析报告、Feign分析报告、文档治理报告

- frontend/design/: Admin-UI分模块打包设计
This commit is contained in:
2026-06-04 09:31:24 +08:00
parent 2e38c53434
commit 19de7e24ec
36 changed files with 5872 additions and 0 deletions
@@ -0,0 +1,236 @@
# MQ 统一推送入口设计文档
> **设计日期**: 2026-06-04
> **版本**: v1.0
> **状态**: 已批准
> **目标**: 创建统一消息队列推送入口 MqClient,封装多 Provider 路由、Action 注入、异常兜底,对标 spring-rui MqDefaultClient
---
## 一、背景与目标
### 1.1 现状分析
当前项目已有基础 MQ 能力:
- `MqService` 接口:提供 `send()` 方法,面向业务开发者直接使用
- `Message<T>` 模型:含 id, topic, payload, headers, timestamp, retryCount
- `RedisMqService` / `RabbitMqService`:分别基于 Redis Pub/Sub 和 RabbitMQ 的实现
- `MqTopic` 注解:用于方法级消息订阅
**存在的问题**
1. 缺乏统一推送门面:业务代码需要直接注入 `MqService` 并选择实现,无法自动按 Provider 路由
2. 无 Provider 抽象:无法在多环境(开发用 Redis、生产用 RabbitMQ)间平滑切换
3. 无 Action 语义:消息缺乏"添加/删除/更新"等业务动作标识
4. 异常处理分散:各实现自行处理异常,缺乏统一兜底
### 1.2 目标定义
1. 创建 `MqClient` 门面类,作为业务层唯一推送入口
2. 引入 `MqPublisher` Provider 接口,实现多 MQ 后端自动路由
3. 扩展 `Message` 模型,支持 action、provider、exchange、delay 等高级字段
4. 保持现有 `MqService` 接口不变,确保向后兼容
5. 所有推送操作统一异常捕获和日志记录
---
## 二、详细设计
### 2.1 整体架构
```
┌─────────────────────────────────────────────────────────────┐
│ 业务层 (Business) │
│ MqClient.publish(...) │
└──────────────────────────┬──────────────────────────────────┘
┌──────────────────────────▼──────────────────────────────────┐
│ MqClient (门面/统一入口) │
│ · 自动从 Spring 容器获取所有 MqPublisher 实现 │
│ · 按 support(MqProvider) 过滤匹配的 Publisher │
│ · 自动注入 action 到 payload │
│ · 统一 try-catch + 日志 │
└──────────────────────────┬──────────────────────────────────┘
┌───────────────┼───────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ RedisMqPublisher │ │ RabbitMqPublisher│ │ FutureProvider │
│ (Redis实现) │ │ (RabbitMQ实现) │ │ (可扩展) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
```
### 2.2 核心组件
| 组件 | 职责 | 位置 |
|------|------|------|
| `MqClient` | 统一推送门面,业务层唯一入口 | `rui-common-mq` |
| `MqPublisher` | Provider 能力接口,定义 support + publish | `rui-common-mq` |
| `MqProvider` | Provider 枚举(RABBITMQ, REDIS | `rui-common-mq` |
| `MqProperties` | 配置属性(默认 provider、topic prefix | `rui-common-mq` |
| `MqAction` | 消息动作枚举(ADDED, DELETED 等) | `rui-common-mq` |
| `Message<T>` | 扩展后的消息模型 | `rui-common-mq` |
### 2.3 数据流
```
启动阶段 (一次)
Spring 注入 List<MqPublisher> → 遍历注册到 EnumMap
publisherMap = { RABBITMQ: RabbitMqPublisher, REDIS: RedisMqPublisher }
运行时 (每次 publish)
MqClient.publish(String topic, MqAction action, T payload)
├─ 1. 构造 Message<T>
├─ 2. 若 action != NONE,将 action 序列化后注入 payload
├─ 3. 若 message.provider == null,使用 MqProperties 默认值
├─ 4. publisherMap.get(provider) → O(1) 直接取到 Publisher
├─ 5. 调用 publisher.publish(message)
└─ 6. catch Exception → log.error,不抛异常
```
### 2.4 接口设计
**MqClient(门面类)**
采用**构造器注入 + 启动预构建 EnumMap**,避免运行时遍历:
```java
@Component
@Slf4j
public class MqClient {
private final MqProperties properties;
private final EnumMap<MqProvider, MqPublisher> publisherMap = new EnumMap<>(MqProvider.class);
public MqClient(MqProperties properties, List<MqPublisher> publishers) {
this.properties = properties;
for (MqPublisher p : publishers) {
publisherMap.put(p.getProvider(), p); // O(1) 注册
}
}
/** 使用默认 Provider 推送 */
public <T> void publish(String topic, T payload);
/** 使用默认 Provider 推送,带 Action */
public <T> void publish(String topic, MqAction action, T payload);
/** 指定 Provider 推送 */
public <T> void publish(MqProvider provider, String topic, T payload);
/** 指定 Provider 推送,带 Action */
public <T> void publish(MqProvider provider, String topic, MqAction action, T payload);
/** 完整 Message 推送 */
public <T> void publish(Message<T> message);
private MqPublisher resolve(MqProvider provider) {
return publisherMap.get(provider); // O(1) 查找
}
}
```
**MqPublisherProvider 接口)**
```java
public interface MqPublisher {
/** 返回该 Publisher 支持的 Provider 类型 */
MqProvider getProvider();
/** 基础推送 */
<T> void publish(String topic, T payload);
/** 完整消息推送 */
<T> void publish(Message<T> message);
}
```
**MqProvider(枚举)**
```java
public enum MqProvider {
RABBITMQ,
REDIS
}
```
**MqProperties(配置)**
```java
@ConfigurationProperties(prefix = "mq")
@Data
public class MqProperties {
private MqProvider provider = MqProvider.RABBITMQ;
private String prefix = "rui";
public String enTopic(String topic) { ... }
public String deTopic(String topic) { ... }
}
```
**MqAction(动作枚举,精简版)**
```java
public enum MqAction {
NONE, ADDED, DELETED, UPDATED, CREATED,
CANCEL, ENABLED, SUCCESSFUL, FAILURE
}
```
### 2.5 扩展现有实现
**RedisMqService** 调整:
- 实现 `MqPublisher` 接口
- `support(MqProvider.REDIS)` 返回 true
- `publish()` 复用现有 `send()` 逻辑
**RabbitMqService** 调整:
- 实现 `MqPublisher` 接口
- `support(MqProvider.RABBITMQ)` 返回 true
- `publish()` 复用现有 `send()` 逻辑
### 2.6 错误处理
- **异常策略**`MqClient` 所有 publish 方法统一 try-catch,记录 error 日志,不抛异常给业务层
- **Provider 不匹配**:若找不到支持该 Provider 的 Publisher,记录 warn 日志
- **Payload 为空**:自动创建空 JSON 对象 `{}`
---
## 三、验收标准
- [ ] `MqClient` 可正常注入并调用 `publish()` 发送消息
- [ ] 通过配置 `mq.provider=redis` 可自动切换到 Redis 实现
- [ ] `publish(topic, MqAction.ADDED, payload)` 发送的消息包含 action 字段
- [ ] 发送异常时不抛异常,仅记录日志
- [ ] 现有 `MqService.send()` 调用不受影响,向后兼容
- [ ] 项目可正常编译通过
---
## 四、风险与依赖
| 风险 | 影响 | 缓解措施 |
|------|------|---------|
| 现有 `MqService` 被多处使用 | 中 | 不修改 `MqService`,新建 `MqPublisher` 接口 |
| `Message<T>` 扩展后序列化兼容性 | 低 | 新增字段均为可空,不影响现有序列化 |
| SpringUtil 在静态方法中可能未初始化 | 低 | MqClient 通过构造器注入,非静态调用 |
---
## 五、对标分析
| 维度 | spring-rui (MqDefaultClient) | 本设计 (MqClient) |
|------|------------------------------|-------------------|
| 门面类名 | `MqDefaultClient` | `MqClient`(更简洁) |
| Provider 接口 | `MqService`(含 support/publish | `MqPublisher`(不冲突现有 `MqService` |
| 配置类名 | `MqAutoConfiguration` | `MqProperties`(更语义化) |
| JSON 框架 | fastjson2 | Jackson(适配本项目) |
| Provider 支持 | MQTT, RABBITMQ, REDIS | RABBITMQ, REDISMQTT 暂不需要) |
| Action 枚举 | `Actions`80+ 项) | `MqAction`(精简 9 项) |
| 包名 | `org.rui.common.mq` | `com.rui.common.mq` |