Files
novalon-manage-system/docs/plans/2026-03-13-multi-module-architecture-refactor-design.md
张翔 dc53a233b9 refactor(domain): 将领域模型移动到common模块
重构项目结构,将分散在各模块的领域模型统一移动到manage-common模块
更新相关依赖和引用路径
调整docker-compose配置和测试标记
添加新的Playwright测试配置
优化Dockerfile构建过程
2026-03-13 19:58:57 +08:00

934 lines
24 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Novalon Manage System 单体多模块架构重构设计文档
**文档版本**: 1.0
**创建日期**: 2026-03-13
**设计目标**: 将 novalon-manage-api 重构为单体多模块架构,实现模块化、统一认证授权、独立部署和性能优化
---
## 1. 架构概述
### 1.1 设计原则
基于参考项目 `everything-is-suitable-api` 的成功实践,novalon-manage-system 将采用**网关 + 单体多模块**的架构模式。
**核心设计原则**
1. **职责单一**:每个模块只负责一个业务领域
2. **依赖单向**:上层模块依赖下层模块,避免循环依赖
3. **接口隔离**:通过网关统一对外暴露API,内部模块解耦
4. **可测试性**:每个模块都可以独立进行单元测试和集成测试
### 1.2 架构图
```
┌─────────────────────────────────────────────────────────────────┐
│ 前端应用 (Vue 3) │
└──────────────────────┬──────────────────────────────────────┘
┌─────────────────┐
│ manage-gateway │ 8080 (网关)
│ (网关) │
└────────┬────────┘
┌─────────────────┐
│ manage-app │ 8081 (后台管理应用)
│ (业务应用) │
└────────┬────────┘
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│manage-sys│ │manage- │ │manage- │
│(系统管理)│ │audit │ │notify │
└──────────┘ └──────────┘ └──────────┘
│ │ │
└────────────┼────────────┘
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│manage- │ │manage- │ │manage- │
│common │ │db │ │file │
│(公共模块)│ │(数据库) │ │(文件管理)│
└──────────┘ └──────────┘ └──────────┘
┌─────────────────┐
│ PostgreSQL │
│ (数据库) │
└─────────────────┘
```
---
## 2. 模块设计
### 2.1 模块层次结构
```
novalon-manage-api/
├── manage-gateway/ # 网关层(8080端口)
│ ├── 路由配置
│ ├── JWT认证过滤器
│ ├── RBAC权限过滤器
│ └── 限流熔断
├── manage-app/ # 应用层(8081端口)
│ ├── 应用启动器
│ ├── 业务模块聚合
│ └── 配置管理
├── manage-sys/ # 系统管理模块
│ ├── 用户管理
│ ├── 角色管理
│ ├── 菜单管理
│ ├── 权限管理
│ ├── 字典管理
│ └── 系统配置
├── manage-audit/ # 审计中心模块
│ ├── 操作日志
│ ├── 登录日志
│ ├── 异常日志
│ └── 安全审计
├── manage-notify/ # 通知中心模块
│ ├── 通知公告
│ ├── 用户消息
│ └── WebSocket实时推送
├── manage-file/ # 文件管理模块
│ ├── 文件上传
│ ├── 文件下载
│ └── 文件预览
├── manage-common/ # 公共模块
│ ├── 工具类
│ ├── JWT工具
│ ├── RBAC过滤器
│ ├── 通用配置
│ └── 缓存配置
└── manage-db/ # 数据库模块
├── 实体类
├── Repository
├── DAO层
└── 数据库迁移
```
### 2.2 模块依赖关系
```
manage-gateway
manage-app
┌─────────┬─────────┬─────────┬─────────┐
│manage- │manage- │manage- │manage- │
│sys │audit │notify │file │
└────┬────┴────┬────┴────┬────┴────┬────┘
│ │ │ │
└─────────┴─────────┴─────────┘
┌─────────┴─────────┐
│manage-common │
└─────────┬─────────┘
manage-db
```
### 2.3 端口分配
- **manage-gateway**: 8080(对外统一入口)
- **manage-app**: 8081(后台管理应用)
- **PostgreSQL**: 5432(数据库)
---
## 3. 认证授权机制
### 3.1 JWT 认证流程
```
1. 用户登录
前端 → Gateway → manage-app → manage-sys
验证用户名密码
生成 JWT Token(包含用户ID、角色、权限)
返回 Token 给前端
2. 后续请求
前端 → Gateway(携带 Token
JWT 认证过滤器验证 Token
解析用户信息(ID、角色、权限)
RBAC 权限过滤器验证权限
转发到 manage-app
```
### 3.2 JWT Token 结构
```json
{
"sub": "user_123", // 用户ID
"username": "admin", // 用户名
"roles": ["ADMIN"], // 角色列表
"permissions": [ // 权限列表
"user:read",
"user:write",
"user:delete",
"role:read",
"role:write"
],
"iat": 1234567890, // 签发时间
"exp": 1234571490 // 过期时间
}
```
### 3.3 RBAC 权限模型
**角色定义**
- **SUPER_ADMIN**: 超级管理员,拥有所有权限
- **ADMIN**: 管理员,拥有系统管理权限
- **AUDITOR**: 审计员,拥有查看权限
- **OPERATOR**: 操作员,拥有基础操作权限
**权限映射**
```
用户管理:
- user:read # 查看用户
- user:write # 创建/修改用户
- user:delete # 删除用户
角色管理:
- role:read # 查看角色
- role:write # 创建/修改角色
- role:delete # 删除角色
菜单管理:
- menu:read # 查看菜单
- menu:write # 创建/修改菜单
- menu:delete # 删除菜单
系统配置:
- config:read # 查看配置
- config:write # 修改配置
审计中心:
- audit:read # 查看审计日志
通知中心:
- notice:read # 查看通知
- notice:write # 发布通知
文件管理:
- file:read # 查看文件
- file:write # 上传文件
- file:delete # 删除文件
```
### 3.4 网关认证授权流程
**Gateway 过滤器链**
```
请求 → 限流过滤器 → JWT 认证过滤器 → RBAC 权限过滤器 → 路由转发
```
**JWT 认证过滤器**
1. 从请求头提取 Token`Authorization: Bearer {token}`
2. 验证 Token 签名和有效期
3. 解析 Token 获取用户信息
4. 将用户信息添加到请求头:`X-User-Id`, `X-User-Roles`, `X-User-Permissions`
5. 验证失败返回 401 Unauthorized
**RBAC 权限过滤器**
1. 从请求头获取用户权限
2. 根据请求路径和方法判断所需权限
3. 验证用户是否拥有所需权限
4. 验证失败返回 403 Forbidden
### 3.5 路由权限映射
```java
/api/sys/users/** user:read (GET), user:write (POST/PUT), user:delete (DELETE)
/api/sys/roles/** role:read (GET), role:write (POST/PUT), role:delete (DELETE)
/api/sys/menus/** menu:read (GET), menu:write (POST/PUT), menu:delete (DELETE)
/api/sys/config/** config:read (GET), config:write (POST/PUT)
/api/audit/logs/** audit:read (GET)
/api/notify/notices/** notice:read (GET), notice:write (POST/PUT)
/api/file/files/** file:read (GET), file:write (POST), file:delete (DELETE)
```
### 3.6 Token 刷新机制
**刷新策略**
- Access Token 有效期:2 小时
- Refresh Token 有效期:7 天
- 前端在 Access Token 过期前 5 分钟使用 Refresh Token 刷新
**刷新流程**
```
前端 → Gateway → manage-app → manage-sys
验证 Refresh Token
生成新的 Access Token
返回新 Token
```
### 3.7 安全增强措施
1. **Token 加密**:使用强加密算法(RS256
2. **Token 黑名单**:使用 Caffeine 缓存存储已注销的 Token
3. **IP 绑定**:可选将 Token 与用户 IP 绑定
4. **设备指纹**:记录登录设备,异常登录时告警
5. **限流保护**:防止暴力破解(登录接口限流:5次/分钟)
---
## 4. 数据流和缓存策略
### 4.1 数据访问架构
**分层设计**
```
Handler 层(API接口)
Service 层(业务逻辑)
Repository 层(数据访问)
DAO 层(数据库操作)
PostgreSQL 数据库
```
### 4.2 Caffeine 缓存策略
**缓存配置**
```yaml
spring:
cache:
type: caffeine
caffeine:
spec: maximumSize=10000,expireAfterWrite=10m
```
**缓存分层**
1. **用户信息缓存**
- 缓存键:`user:{userId}`
- 缓存内容:用户基本信息、角色、权限
- 过期时间:5 分钟
- 最大容量:1000 条
2. **角色权限缓存**
- 缓存键:`role:{roleId}`
- 缓存内容:角色信息、关联权限
- 过期时间:10 分钟
- 最大容量:500 条
3. **菜单树缓存**
- 缓存键:`menu:tree:{userId}`
- 缓存内容:用户可访问的菜单树
- 过期时间:10 分钟
- 最大容量:1000 条
4. **字典数据缓存**
- 缓存键:`dict:{dictType}`
- 缓存内容:字典类型对应的字典数据
- 过期时间:30 分钟
- 最大容量:2000 条
5. **系统配置缓存**
- 缓存键:`config:{configKey}`
- 缓存内容:系统配置项
- 过期时间:30 分钟
- 最大容量:500 条
6. **Token 黑名单缓存**
- 缓存键:`token:blacklist:{tokenId}`
- 缓存内容:已注销的 Token ID
- 过期时间:Token 剩余有效期
- 最大容量:10000 条
### 4.3 缓存更新策略
**Cache-Aside 模式**
```
读取数据:
1. 先查缓存
2. 缓存命中,直接返回
3. 缓存未命中,查数据库
4. 将数据写入缓存
5. 返回数据
写入数据:
1. 先更新数据库
2. 删除相关缓存
3. 下次读取时重新加载缓存
```
**缓存失效场景**
- 用户信息更新 → 删除用户缓存
- 角色权限变更 → 删除角色缓存、用户缓存
- 菜单配置变更 → 删除菜单树缓存
- 字典数据变更 → 删除字典缓存
- 系统配置变更 → 删除配置缓存
- 用户登出 → 添加 Token 到黑名单缓存
### 4.4 数据流示例
**用户登录流程**
```
1. 前端请求登录
POST /api/auth/login
2. Gateway 验证(限流检查)
3. manage-app 接收请求
4. manage-sys 验证用户名密码
5. 查询用户信息(先查缓存,未命中查数据库)
6. 查询用户角色和权限(先查缓存,未命中查数据库)
7. 生成 JWT Token
8. 返回 Token 和用户信息
9. 缓存用户信息(5分钟)
```
**获取用户菜单流程**
```
1. 前端请求菜单
GET /api/sys/menus
2. Gateway 验证 JWT Token
3. Gateway 验证 RBAC 权限(menu:read
4. manage-app 接收请求
5. manage-sys 查询菜单树
6. 先查缓存(menu:tree:{userId}
7. 缓存命中,直接返回
8. 缓存未命中,查询数据库
9. 构建菜单树
10. 写入缓存(10分钟)
11. 返回菜单树
```
### 4.5 数据库连接池配置
**R2DBC 连接池**
```yaml
spring:
r2dbc:
pool:
initial-size: 10 # 初始连接数
max-size: 50 # 最大连接数
max-idle-time: 30m # 最大空闲时间
max-life-time: 1h # 连接最大生命周期
acquire-timeout: 5s # 获取连接超时时间
```
### 4.6 性能优化策略
1. **批量查询优化**
- 使用 IN 查询替代循环查询
- 使用 JOIN 减少数据库往返
2. **索引优化**
- 用户表:username, email, phone
- 角色表:role_code
- 菜单表:parent_id, menu_type
- 日志表:create_time, user_id
3. **分页查询优化**
- 使用游标分页(基于 ID
- 避免 OFFSET 过大
4. **异步处理**
- 日志记录异步化
- 消息推送异步化
5. **响应式编程**
- 使用 WebFlux 非阻塞 I/O
- 使用 R2DBC 非阻塞数据库访问
### 4.7 Token 黑名单实现(Caffeine 版本)
```java
@Configuration
public class TokenBlacklistConfig {
@Bean
public Cache<String, Boolean> tokenBlacklistCache() {
return Caffeine.newBuilder()
.maximumSize(10000)
.expireAfterWrite(2, TimeUnit.HOURS) // 与 Access Token 过期时间一致
.build();
}
}
@Service
public class TokenBlacklistService {
@Autowired
private Cache<String, Boolean> tokenBlacklistCache;
public void addToBlacklist(String tokenId) {
tokenBlacklistCache.put(tokenId, true);
}
public boolean isBlacklisted(String tokenId) {
return tokenBlacklistCache.getIfPresent(tokenId) != null;
}
}
```
---
## 5. 部署方案
### 5.1 Docker 部署架构
**容器化架构**
```
┌─────────────────────────────────────────────────────────────────┐
│ Docker Network │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Nginx │ │ Gateway │ │ App │ │
│ │ :80 │ │ :8080 │ │ :8081 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │ │
│ └─────────────────┴─────────────────┘ │
│ │ │
│ ┌────────┴────────┐ │
│ │ PostgreSQL │ │
│ │ :5432 │ │
│ └────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
### 5.2 Docker Compose 配置
```yaml
version: '3.8'
services:
# PostgreSQL 数据库
postgres:
image: postgres:15-alpine
container_name: novalon-postgres
environment:
POSTGRES_DB: novalon_manage
POSTGRES_USER: ${DB_USERNAME:-postgres}
POSTGRES_PASSWORD: ${DB_PASSWORD:-postgres}
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./docs/sql:/docker-entrypoint-initdb.d
networks:
- novalon-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
# 网关服务
manage-gateway:
build:
context: ./novalon-manage-api
dockerfile: manage-gateway/Dockerfile
container_name: novalon-gateway
ports:
- "8080:8080"
environment:
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod}
JWT_SECRET: ${JWT_SECRET}
JWT_EXPIRATION: ${JWT_EXPIRATION:-7200}
APP_SERVICE_URL: http://manage-app:8081
depends_on:
manage-app:
condition: service_healthy
networks:
- novalon-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
# 应用服务
manage-app:
build:
context: ./novalon-manage-api
dockerfile: manage-app/Dockerfile
container_name: novalon-app
ports:
- "8081:8081"
environment:
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod}
DB_HOST: postgres
DB_PORT: 5432
DB_NAME: novalon_manage
DB_USERNAME: ${DB_USERNAME:-postgres}
DB_PASSWORD: ${DB_PASSWORD:-postgres}
JWT_SECRET: ${JWT_SECRET}
depends_on:
postgres:
condition: service_healthy
networks:
- novalon-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8081/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
# Nginx 反向代理(可选)
nginx:
image: nginx:alpine
container_name: novalon-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/ssl:/etc/nginx/ssl
depends_on:
- manage-gateway
networks:
- novalon-network
volumes:
postgres_data:
networks:
novalon-network:
driver: bridge
```
### 5.3 环境变量配置
**.env 文件**
```bash
# 数据库配置
DB_USERNAME=postgres
DB_PASSWORD=your_secure_password
# JWT 配置
JWT_SECRET=your_jwt_secret_key_minimum_256_bits
JWT_EXPIRATION=7200
# Spring Profile
SPRING_PROFILES_ACTIVE=prod
```
---
## 6. 迁移计划
### 6.1 阶段一:准备工作(1-2天)
**Task 1: 创建新模块结构**
- 创建 manage-gateway 模块
- 创建 manage-app 模块
- 创建 manage-common 模块
- 创建 manage-db 模块
- 创建 manage-audit 模块
- 创建 manage-notify 模块
- 创建 manage-file 模块
**Task 2: 配置父 POM**
- 更新父 POM 添加新模块
- 配置依赖管理
- 配置插件管理
**Task 3: 数据库迁移准备**
- 备份现有数据库
- 检查 Flyway 迁移脚本
- 准备新的迁移脚本
### 6.2 阶段二:模块拆分(3-5天)
**Task 4: 提取公共模块(manage-common**
- 提取工具类到 manage-common
- 提取 JWT 工具类
- 提取 RBAC 过滤器
- 提取通用配置
- 提取缓存配置
**Task 5: 提取数据库模块(manage-db**
- 提取实体类到 manage-db
- 提取 Repository 接口
- 提取 DAO 层
- 提取数据库迁移脚本
**Task 6: 拆分系统管理模块(manage-sys)**
- 保留用户、角色、菜单、权限、字典、配置功能
- 移除审计、通知、文件相关代码
- 更新依赖关系
**Task 7: 创建审计中心模块(manage-audit**
- 迁移操作日志功能
- 迁移登录日志功能
- 迁移异常日志功能
- 迁移安全审计功能
**Task 8: 创建通知中心模块(manage-notify**
- 迁移通知公告功能
- 迁移用户消息功能
- 迁移 WebSocket 实时推送功能
**Task 9: 创建文件管理模块(manage-file**
- 迁移文件上传功能
- 迁移文件下载功能
- 迁移文件预览功能
### 6.3 阶段三:网关和应用层(2-3天)
**Task 10: 创建网关模块(manage-gateway**
- 配置路由规则
- 实现 JWT 认证过滤器
- 实现 RBAC 权限过滤器
- 实现限流熔断
- 配置健康检查
**Task 11: 创建应用模块(manage-app**
- 创建应用启动器
- 配置模块聚合
- 配置应用配置
- 配置 Actuator 端点
**Task 12: 配置模块依赖**
- 配置 manage-app 依赖所有业务模块
- 配置业务模块依赖 manage-db 和 manage-common
- 验证依赖关系正确性
### 6.4 阶段四:测试和优化(2-3天)
**Task 13: 单元测试**
- 为每个模块编写单元测试
- 确保测试覆盖率 ≥ 80%
- 修复测试失败
**Task 14: 集成测试**
- 测试网关路由
- 测试认证授权
- 测试模块间调用
- 测试缓存功能
**Task 15: 性能测试**
- 使用 K6 进行性能测试
- 优化慢查询
- 优化缓存策略
- 调整 JVM 参数
**Task 16: 安全测试**
- OWASP 依赖检查
- SQL 注入测试
- XSS 测试
- CSRF 测试
### 6.5 阶段五:部署和切换(1-2天)
**Task 17: Docker 部署**
- 编写 Dockerfile
- 编写 docker-compose.yml
- 配置环境变量
- 本地部署测试
**Task 18: 生产部署**
- 备份生产环境
- 部署新版本
- 验证功能正常
- 监控系统运行
**Task 19: 灰度切换**
- 切换部分流量到新版本
- 监控错误率和性能
- 逐步扩大流量
- 全量切换
**Task 20: 回滚准备**
- 准备回滚脚本
- 验证回滚流程
- 文档化回滚步骤
---
## 7. 风险控制
### 7.1 风险识别
1. **数据丢失风险**:迁移过程中数据不一致
2. **功能回归风险**:模块拆分导致功能异常
3. **性能下降风险**:网关层增加延迟
4. **部署失败风险**Docker 部署出现问题
### 7.2 风险缓解
1. **数据备份**:迁移前完整备份数据库
2. **充分测试**:单元测试、集成测试、E2E 测试
3. **灰度发布**:逐步切换流量,监控指标
4. **快速回滚**:准备回滚方案,确保可以快速恢复
---
## 8. 监控指标
### 8.1 应用监控
- 健康检查:`/actuator/health`
- 性能指标:`/actuator/metrics`
- JVM 指标:内存、GC、线程
### 8.2 业务监控
- 请求成功率
- 响应时间(P50, P95, P99
- 错误率
- 并发用户数
### 8.3 数据库监控
- 连接池使用率
- 慢查询数量
- 数据库 CPU 使用率
---
## 9. 技术栈
### 9.1 后端技术栈
- **Java**: 21
- **Spring Boot**: 3.4.1
- **Spring WebFlux**: 响应式编程框架
- **Spring Security**: 安全框架
- **Spring Data R2DBC**: 响应式数据库访问
- **PostgreSQL**: 关系型数据库
- **Flyway**: 数据库版本管理
- **JWT**: 无状态认证
- **Caffeine**: 本地缓存
- **MapStruct**: 对象映射
- **Lombok**: 简化代码
### 9.2 构建和部署
- **Maven**: 项目构建工具
- **Docker**: 容器化
- **Docker Compose**: 容器编排
- **Nginx**: 反向代理
### 9.3 测试和监控
- **JUnit 5**: 单元测试框架
- **Reactor Test**: 响应式测试
- **K6**: 性能测试
- **Spring Boot Actuator**: 应用监控
- **SpotBugs**: 静态代码分析
- **OWASP Dependency Check**: 依赖安全检查
- **JaCoCo**: 代码覆盖率
---
## 10. 成功标准
### 10.1 功能验收标准
- ✅ 所有现有功能正常工作
- ✅ 网关路由正确转发请求
- ✅ JWT 认证正常工作
- ✅ RBAC 权限控制正确
- ✅ 缓存功能正常工作
- ✅ WebSocket 实时推送正常
### 10.2 性能指标
- ✅ API 响应时间 P95 < 200ms
- ✅ API 响应时间 P99 < 500ms
- ✅ 请求成功率 > 99.9%
- ✅ 数据库连接池使用率 < 80%
- ✅ 缓存命中率 > 70%
### 10.3 质量指标
- ✅ 单元测试覆盖率 ≥ 80%
- ✅ 集成测试覆盖率 ≥ 60%
- ✅ 无严重安全漏洞
- ✅ 无严重代码质量问题
---
## 11. 后续优化方向
### 11.1 短期优化(1-3个月)
- 引入 API 文档自动生成
- 完善监控告警系统
- 优化慢查询
- 增加缓存命中率
### 11.2 中期优化(3-6个月)
- 引入分布式追踪(如 Jaeger
- 实现灰度发布功能
- 优化数据库索引
- 实现 API 版本管理
### 11.3 长期优化(6-12个月)
- 考虑微服务化改造
- 引入服务网格(如 Istio
- 实现多租户支持
- 引入事件驱动架构
---
## 附录
### A. 参考资料
- everything-is-suitable-api 双应用架构文档
- Spring Boot 官方文档
- Spring Security 官方文档
- PostgreSQL 官方文档
- Caffeine 官方文档
### B. 术语表
- **RBAC**: Role-Based Access Control,基于角色的访问控制
- **JWT**: JSON Web TokenJSON 格式的 Web Token
- **R2DBC**: Reactive Relational Database Connectivity,响应式数据库连接
- **Caffeine**: 高性能 Java 缓存库
- **Flyway**: 数据库迁移工具
- **Actuator**: Spring Boot 应用监控端点
---
**文档结束**