重构项目结构,将分散在各模块的领域模型统一移动到manage-common模块 更新相关依赖和引用路径 调整docker-compose配置和测试标记 添加新的Playwright测试配置 优化Dockerfile构建过程
24 KiB
Novalon Manage System 单体多模块架构重构设计文档
文档版本: 1.0 创建日期: 2026-03-13 设计目标: 将 novalon-manage-api 重构为单体多模块架构,实现模块化、统一认证授权、独立部署和性能优化
1. 架构概述
1.1 设计原则
基于参考项目 everything-is-suitable-api 的成功实践,novalon-manage-system 将采用网关 + 单体多模块的架构模式。
核心设计原则:
- 职责单一:每个模块只负责一个业务领域
- 依赖单向:上层模块依赖下层模块,避免循环依赖
- 接口隔离:通过网关统一对外暴露API,内部模块解耦
- 可测试性:每个模块都可以独立进行单元测试和集成测试
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 结构
{
"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 认证过滤器:
- 从请求头提取 Token:
Authorization: Bearer {token} - 验证 Token 签名和有效期
- 解析 Token 获取用户信息
- 将用户信息添加到请求头:
X-User-Id,X-User-Roles,X-User-Permissions - 验证失败返回 401 Unauthorized
RBAC 权限过滤器:
- 从请求头获取用户权限
- 根据请求路径和方法判断所需权限
- 验证用户是否拥有所需权限
- 验证失败返回 403 Forbidden
3.5 路由权限映射
/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 安全增强措施
- Token 加密:使用强加密算法(RS256)
- Token 黑名单:使用 Caffeine 缓存存储已注销的 Token
- IP 绑定:可选将 Token 与用户 IP 绑定
- 设备指纹:记录登录设备,异常登录时告警
- 限流保护:防止暴力破解(登录接口限流:5次/分钟)
4. 数据流和缓存策略
4.1 数据访问架构
分层设计:
Handler 层(API接口)
↓
Service 层(业务逻辑)
↓
Repository 层(数据访问)
↓
DAO 层(数据库操作)
↓
PostgreSQL 数据库
4.2 Caffeine 缓存策略
缓存配置:
spring:
cache:
type: caffeine
caffeine:
spec: maximumSize=10000,expireAfterWrite=10m
缓存分层:
-
用户信息缓存
- 缓存键:
user:{userId} - 缓存内容:用户基本信息、角色、权限
- 过期时间:5 分钟
- 最大容量:1000 条
- 缓存键:
-
角色权限缓存
- 缓存键:
role:{roleId} - 缓存内容:角色信息、关联权限
- 过期时间:10 分钟
- 最大容量:500 条
- 缓存键:
-
菜单树缓存
- 缓存键:
menu:tree:{userId} - 缓存内容:用户可访问的菜单树
- 过期时间:10 分钟
- 最大容量:1000 条
- 缓存键:
-
字典数据缓存
- 缓存键:
dict:{dictType} - 缓存内容:字典类型对应的字典数据
- 过期时间:30 分钟
- 最大容量:2000 条
- 缓存键:
-
系统配置缓存
- 缓存键:
config:{configKey} - 缓存内容:系统配置项
- 过期时间:30 分钟
- 最大容量:500 条
- 缓存键:
-
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 连接池:
spring:
r2dbc:
pool:
initial-size: 10 # 初始连接数
max-size: 50 # 最大连接数
max-idle-time: 30m # 最大空闲时间
max-life-time: 1h # 连接最大生命周期
acquire-timeout: 5s # 获取连接超时时间
4.6 性能优化策略
-
批量查询优化
- 使用 IN 查询替代循环查询
- 使用 JOIN 减少数据库往返
-
索引优化
- 用户表:username, email, phone
- 角色表:role_code
- 菜单表:parent_id, menu_type
- 日志表:create_time, user_id
-
分页查询优化
- 使用游标分页(基于 ID)
- 避免 OFFSET 过大
-
异步处理
- 日志记录异步化
- 消息推送异步化
-
响应式编程
- 使用 WebFlux 非阻塞 I/O
- 使用 R2DBC 非阻塞数据库访问
4.7 Token 黑名单实现(Caffeine 版本)
@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 配置
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 文件:
# 数据库配置
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 风险识别
- 数据丢失风险:迁移过程中数据不一致
- 功能回归风险:模块拆分导致功能异常
- 性能下降风险:网关层增加延迟
- 部署失败风险:Docker 部署出现问题
7.2 风险缓解
- 数据备份:迁移前完整备份数据库
- 充分测试:单元测试、集成测试、E2E 测试
- 灰度发布:逐步切换流量,监控指标
- 快速回滚:准备回滚方案,确保可以快速恢复
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 Token,JSON 格式的 Web Token
- R2DBC: Reactive Relational Database Connectivity,响应式数据库连接
- Caffeine: 高性能 Java 缓存库
- Flyway: 数据库迁移工具
- Actuator: Spring Boot 应用监控端点
文档结束