|
|
|
|
|
# RuoYi-Vue 后端架构分析
|
|
|
|
|
|
|
|
|
|
|
|
> 版本:3.8.0 | 分析日期:2026-06-28 | 框架:Spring Boot 2.5.8
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 1. 分层架构分析
|
|
|
|
|
|
|
|
|
|
|
|
### 1.1 整体分层概览
|
|
|
|
|
|
|
|
|
|
|
|
项目采用经典的 **四层架构**:Controller → Service → Mapper → Domain,各层职责清晰,通过 Maven 多模块进行物理隔离。
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ ruoyi-admin (启动层) │
|
|
|
|
|
|
│ ┌─────────────┐ ┌─────────────┐ ┌──────────────────────┐ │
|
|
|
|
|
|
│ │ Controller │ │ Config │ │ Application │ │
|
|
|
|
|
|
│ │ (18个) │ │ (Swagger) │ │ RuoYiApplication │ │
|
|
|
|
|
|
│ └──────┬──────┘ └─────────────┘ └──────────────────────┘ │
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
│ ▼ │
|
|
|
|
|
|
│ ┌──────────────────────────────────────────────────────┐ │
|
|
|
|
|
|
│ │ ruoyi-framework (框架层) │ │
|
|
|
|
|
|
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │ │
|
|
|
|
|
|
│ │ │ Aspect │ │ Security │ │ Config │ │ Manager │ │ │
|
|
|
|
|
|
│ │ │ (4个切面)│ │ (JWT) │ │ (12个) │ │ (异步) │ │ │
|
|
|
|
|
|
│ │ └──────────┘ └──────────┘ └──────────┘ └─────────┘ │ │
|
|
|
|
|
|
│ └──────────────────────┬───────────────────────────────┘ │
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
│ ┌───────────────┼───────────────┐ │
|
|
|
|
|
|
│ ▼ ▼ ▼ │
|
|
|
|
|
|
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
|
|
|
|
|
|
│ │ruoyi- │ │book- │ │ stock- │ │
|
|
|
|
|
|
│ │system │ │system │ │ system │ │
|
|
|
|
|
|
│ │(15 Mapper│ │(6 Mapper │ │ (9 Mapper │ │
|
|
|
|
|
|
│ │ 12 Service│ │ 6 Service│ │ ... │ │
|
|
|
|
|
|
│ │ 12 Domain)│ │ 6 Domain)│ │ │ │
|
|
|
|
|
|
│ └──────────┘ └──────────┘ └──────────────┘ │
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
│ ▼ │
|
|
|
|
|
|
│ ┌──────────────────────────────────────────────────────┐ │
|
|
|
|
|
|
│ │ ruoyi-common (通用工具层) │ │
|
|
|
|
|
|
│ │ BaseController / AjaxResult / BaseEntity / 注解 / │ │
|
|
|
|
|
|
│ │ 工具类(20+) / 异常类 / 过滤器 / 常量 │ │
|
|
|
|
|
|
│ └──────────────────────────────────────────────────────┘ │
|
|
|
|
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 1.2 Controller 层分析
|
|
|
|
|
|
|
|
|
|
|
|
**文件位置**:`ruoyi-admin/src/main/java/com/ruoyi/web/controller/`
|
|
|
|
|
|
|
|
|
|
|
|
#### Controller 统计
|
|
|
|
|
|
|
|
|
|
|
|
| 分类 | 数量 | 文件列表 |
|
|
|
|
|
|
|------|------|----------|
|
|
|
|
|
|
| 系统管理 | 13 | SysConfigController, SysDeptController, SysDictDataController, SysDictTypeController, SysIndexController, SysLoginController, SysMenuController, SysNoticeController, SysPostController, SysProfileController, SysRegisterController, SysRoleController, SysUserController |
|
|
|
|
|
|
| 监控管理 | 5 | CacheController, ServerController, SysLogininforController, SysOperlogController, SysUserOnlineController |
|
|
|
|
|
|
| 业务模块 | 6 | AccountBookController, AccountController, OperationsController, StatisticsController, StatisticsRemainController, StatisticsTotalController |
|
|
|
|
|
|
| 工具/公共 | 4 | CaptchaController, CommonController, SwaggerController, TestController |
|
|
|
|
|
|
| **合计** | **28** | — |
|
|
|
|
|
|
|
|
|
|
|
|
#### 设计模式
|
|
|
|
|
|
|
|
|
|
|
|
1. **统一继承 BaseController**:所有 Controller 继承 `BaseController`,获得分页、响应、用户上下文等通用能力。
|
|
|
|
|
|
|
|
|
|
|
|
2. **标准 CRUD 接口模式**:
|
|
|
|
|
|
```
|
|
|
|
|
|
GET /list → 分页列表查询
|
|
|
|
|
|
GET /{id} → 详情查询
|
|
|
|
|
|
POST / → 新增
|
|
|
|
|
|
PUT / → 修改
|
|
|
|
|
|
DELETE /{ids} → 批量删除
|
|
|
|
|
|
POST /export → Excel 导出
|
|
|
|
|
|
POST /importData → Excel 导入
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
3. **权限注解驱动**:每个接口通过 `@PreAuthorize("@ss.hasPermi('module:entity:action')")` 进行权限控制。
|
|
|
|
|
|
|
|
|
|
|
|
4. **操作日志注解**:通过 `@Log(title = "模块名", businessType = BusinessType.XXX)` 声明式记录操作日志。
|
|
|
|
|
|
|
|
|
|
|
|
### 1.3 Service 层分析
|
|
|
|
|
|
|
|
|
|
|
|
**文件位置**:
|
|
|
|
|
|
- 系统模块:`ruoyi-system/src/main/java/com/ruoyi/system/service/`
|
|
|
|
|
|
- 账务模块:`book-system/src/main/java/com/ruoyi/booksystem/service/`
|
|
|
|
|
|
|
|
|
|
|
|
#### 接口与实现分离
|
|
|
|
|
|
|
|
|
|
|
|
采用标准的 **接口 + 实现类** 模式:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
ISysUserService (接口)
|
|
|
|
|
|
└── SysUserServiceImpl (实现)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
| 模块 | 接口数 | 实现类数 |
|
|
|
|
|
|
|------|--------|----------|
|
|
|
|
|
|
| ruoyi-system | 12 | 12 |
|
|
|
|
|
|
| book-system | 6 | 6 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 事务管理
|
|
|
|
|
|
|
|
|
|
|
|
使用 `@Transactional` 注解管理事务,主要在以下场景使用:
|
|
|
|
|
|
|
|
|
|
|
|
| 场景 | 方法示例 |
|
|
|
|
|
|
|------|----------|
|
|
|
|
|
|
| 新增用户(含角色/岗位关联) | `insertUser()` |
|
|
|
|
|
|
| 修改用户(含角色/岗位关联) | `updateUser()` |
|
|
|
|
|
|
| 删除用户(含关联清理) | `deleteUserById()`, `deleteUserByIds()` |
|
|
|
|
|
|
| 用户授权角色 | `insertUserAuth()` |
|
|
|
|
|
|
|
|
|
|
|
|
**事务策略特点**:
|
|
|
|
|
|
- 仅在涉及多表操作的复合方法上加 `@Transactional`
|
|
|
|
|
|
- 简单 CRUD(如 `updateUserStatus`)不使用事务
|
|
|
|
|
|
- 使用默认的 `REQUIRED` 传播级别和 `RuntimeException` 回滚策略
|
|
|
|
|
|
|
|
|
|
|
|
#### 数据权限注解
|
|
|
|
|
|
|
|
|
|
|
|
Service 层通过 `@DataScope(deptAlias = "d", userAlias = "u")` 注解实现数据权限过滤,在方法执行前由 AOP 切面动态注入 SQL 过滤条件。
|
|
|
|
|
|
|
|
|
|
|
|
### 1.4 Mapper 层分析
|
|
|
|
|
|
|
|
|
|
|
|
**文件位置**:
|
|
|
|
|
|
- XML 映射:`{module}/src/main/resources/mapper/{module}/`
|
|
|
|
|
|
- Java 接口:`{module}/src/main/java/com/ruoyi/{module}/mapper/`
|
|
|
|
|
|
|
|
|
|
|
|
#### MyBatis 映射文件统计
|
|
|
|
|
|
|
|
|
|
|
|
| 模块 | XML 文件数 | 主要功能 |
|
|
|
|
|
|
|------|-----------|----------|
|
|
|
|
|
|
| ruoyi-system | 11 | 用户、角色、菜单、部门、字典、岗位、日志、配置、公告 |
|
|
|
|
|
|
| book-system | 6 | 账户、账本、操作、统计 |
|
|
|
|
|
|
| stock-system | 9 | 股票、行情、财务、趋势 |
|
|
|
|
|
|
| ruoyi-quartz | 2 | 定时任务 |
|
|
|
|
|
|
| ruoyi-generator | 2 | 代码生成 |
|
|
|
|
|
|
| **合计** | **30** | — |
|
|
|
|
|
|
|
|
|
|
|
|
#### 动态 SQL 使用
|
|
|
|
|
|
|
|
|
|
|
|
以 `SysUserMapper.xml` 为例,大量使用 MyBatis 动态 SQL:
|
|
|
|
|
|
|
|
|
|
|
|
| 标签 | 用途 | 示例 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `<if>` | 条件查询 | `<if test="userName != null and userName != ''">` |
|
|
|
|
|
|
| `<foreach>` | 批量操作 | `<foreach collection="array" item="userId">` |
|
|
|
|
|
|
| `<include>` | SQL 片段复用 | `<include refid="selectUserVo"/>` |
|
|
|
|
|
|
| `<sql>` | 定义可复用片段 | `<sql id="selectUserVo">` |
|
|
|
|
|
|
| `<set>` | 动态更新 | `<set><if test="...">field = #{...},</if></set>` |
|
|
|
|
|
|
| `${params.dataScope}` | 数据权限注入 | 由 DataScopeAspect 动态拼接 |
|
|
|
|
|
|
|
|
|
|
|
|
#### ResultMap 关联映射
|
|
|
|
|
|
|
|
|
|
|
|
使用 `<association>` 和 `<collection>` 实现一对多关联查询:
|
|
|
|
|
|
```xml
|
|
|
|
|
|
<association property="dept" javaType="SysDept" resultMap="deptResult" />
|
|
|
|
|
|
<collection property="roles" javaType="java.util.List" resultMap="RoleResult" />
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 1.5 Domain 层分析
|
|
|
|
|
|
|
|
|
|
|
|
#### 基类体系
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
BaseEntity (基础实体)
|
|
|
|
|
|
├── searchValue, createBy, createTime, updateBy, updateTime, remark, params
|
|
|
|
|
|
│
|
|
|
|
|
|
├── TreeEntity (树形实体)
|
|
|
|
|
|
│ └── parentId, ancestors
|
|
|
|
|
|
│
|
|
|
|
|
|
└── AjaxResult (统一响应)
|
|
|
|
|
|
└── code, msg, data (继承 HashMap)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 核心实体类
|
|
|
|
|
|
|
|
|
|
|
|
| 实体 | 位置 | 用途 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| SysUser | ruoyi-common | 用户信息 |
|
|
|
|
|
|
| SysRole | ruoyi-common | 角色信息 |
|
|
|
|
|
|
| SysMenu | ruoyi-common | 菜单/权限 |
|
|
|
|
|
|
| SysDept | ruoyi-common | 部门信息 |
|
|
|
|
|
|
| LoginUser | ruoyi-common | 登录用户上下文 |
|
|
|
|
|
|
| SysConfig/SysNotice/SysOperLog | ruoyi-system | 系统业务实体 |
|
|
|
|
|
|
| Account/AccountBook/Statistics | book-system | 账务业务实体 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2. 安全配置
|
|
|
|
|
|
|
|
|
|
|
|
### 2.1 Spring Security 配置
|
|
|
|
|
|
|
|
|
|
|
|
**配置文件**:`ruoyi-framework/.../config/SecurityConfig.java`
|
|
|
|
|
|
|
|
|
|
|
|
#### 认证流程
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
HTTP Request
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
┌──────────────────────┐
|
|
|
|
|
|
│ CorsFilter │ ← 跨域处理
|
|
|
|
|
|
└──────────┬───────────┘
|
|
|
|
|
|
▼
|
|
|
|
|
|
┌──────────────────────┐
|
|
|
|
|
|
│ JwtAuthentication │ ← JWT Token 验证
|
|
|
|
|
|
│ TokenFilter │
|
|
|
|
|
|
└──────────┬───────────┘
|
|
|
|
|
|
▼
|
|
|
|
|
|
┌──────────────────────┐
|
|
|
|
|
|
│ UsernamePassword │ ← Spring Security 内置
|
|
|
|
|
|
│ AuthenticationFilter │
|
|
|
|
|
|
└──────────┬───────────┘
|
|
|
|
|
|
▼
|
|
|
|
|
|
┌──────────────────────┐
|
|
|
|
|
|
│ Controller Handler │
|
|
|
|
|
|
└──────────────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 安全配置要点
|
|
|
|
|
|
|
|
|
|
|
|
| 配置项 | 值/策略 |
|
|
|
|
|
|
|--------|---------|
|
|
|
|
|
|
| CSRF | 禁用(无状态 Token 认证) |
|
|
|
|
|
|
| Session | STATELESS(无会话) |
|
|
|
|
|
|
| 密码加密 | BCryptPasswordEncoder |
|
|
|
|
|
|
| 匿名路径 | `/login`, `/register`, `/captchaImage` |
|
|
|
|
|
|
| 公共资源 | `/**/*.html`, `/**/*.css`, `/**/*.js`, `/profile/**` |
|
|
|
|
|
|
| Swagger | `/swagger-ui.html`, `/swagger-resources/**` |
|
|
|
|
|
|
| 监控 | `/druid/**` |
|
|
|
|
|
|
| 其他所有请求 | 需要认证 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 方法级安全
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
|
|
|
|
|
```
|
|
|
|
|
|
- 启用 `@PreAuthorize` 和 `@PostAuthorize` 方法级权限控制
|
|
|
|
|
|
- 启用 `@Secured` 注解支持
|
|
|
|
|
|
|
|
|
|
|
|
### 2.2 JWT Token 机制
|
|
|
|
|
|
|
|
|
|
|
|
**核心类**:`ruoyi-framework/.../web/service/TokenService.java`
|
|
|
|
|
|
|
|
|
|
|
|
#### Token 结构
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
JWT Header + Payload Redis 缓存
|
|
|
|
|
|
┌─────────────────────┐ ┌──────────────────────┐
|
|
|
|
|
|
│ { │ │ login_tokens:{uuid} │
|
|
|
|
|
|
│ LOGIN_USER_KEY │──uuid──→ │ { │
|
|
|
|
|
|
│ : uuid │ │ LoginUser Object │
|
|
|
|
|
|
│ } │ │ TTL: 30min │
|
|
|
|
|
|
└─────────────────────┘ └──────────────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 关键参数
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 配置项 | 默认值 |
|
|
|
|
|
|
|------|--------|--------|
|
|
|
|
|
|
| Token Header | `token.header` | `Authorization` |
|
|
|
|
|
|
| Token Secret | `token.secret` | 自定义密钥 |
|
|
|
|
|
|
| Token 有效期 | `token.expireTime` | 30 分钟 |
|
|
|
|
|
|
| 自动刷新阈值 | 硬编码 | 剩余不足 20 分钟时刷新 |
|
|
|
|
|
|
|
|
|
|
|
|
#### Token 工作流程
|
|
|
|
|
|
|
|
|
|
|
|
1. **登录** → 生成 UUID → 存入 Redis → JWT 携带 UUID → 返回 Token
|
|
|
|
|
|
2. **请求** → 提取 Token → 解析 UUID → Redis 获取用户 → 验证有效期
|
|
|
|
|
|
3. **刷新** → 距过期不足 20 分钟 → 自动续期 Redis TTL
|
|
|
|
|
|
4. **登出** → 删除 Redis 中的用户缓存
|
|
|
|
|
|
|
|
|
|
|
|
### 2.3 权限控制体系
|
|
|
|
|
|
|
|
|
|
|
|
#### 权限模型
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户 (SysUser)
|
|
|
|
|
|
└── 角色 (SysRole) [多对多]
|
|
|
|
|
|
└── 菜单/权限 (SysMenu) [多对多]
|
|
|
|
|
|
└── 权限标识: "system:user:list"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 三种权限控制方式
|
|
|
|
|
|
|
|
|
|
|
|
| 方式 | 注解/实现 | 层级 | 用途 |
|
|
|
|
|
|
|------|-----------|------|------|
|
|
|
|
|
|
| URL 级 | Spring Security `antMatchers` | 网关 | 公开/匿名资源 |
|
|
|
|
|
|
| 方法级 | `@PreAuthorize("@ss.hasPermi('...')")` | Controller | 功能权限 |
|
|
|
|
|
|
| 数据级 | `@DataScope(deptAlias, userAlias)` | Service | 数据范围过滤 |
|
|
|
|
|
|
|
|
|
|
|
|
#### PermissionService 权限判断
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
@Service("ss")
|
|
|
|
|
|
public class PermissionService {
|
|
|
|
|
|
hasPermi("system:user:list") // 是否拥有某权限
|
|
|
|
|
|
lacksPermi("system:user:list") // 是否不拥有某权限
|
|
|
|
|
|
hasAnyPermi("a,b,c") // 是否拥有任一权限
|
|
|
|
|
|
hasRole("admin") // 是否拥有某角色
|
|
|
|
|
|
lacksRole("admin") // 是否不拥有某角色
|
|
|
|
|
|
hasAnyRoles("admin,common") // 是否拥有任一角色
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
权限标识约定:`{模块}:{实体}:{操作}`,如 `system:user:list`、`booksystem:account:add`。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 3. AOP 切面分析
|
|
|
|
|
|
|
|
|
|
|
|
**文件位置**:`ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/`
|
|
|
|
|
|
|
|
|
|
|
|
### 3.1 切面总览
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
┌─────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ AOP 切面 (4个) │
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ┌──────────────┐ ┌──────────────┐ │
|
|
|
|
|
|
│ │ LogAspect │ │ DataScope │ │
|
|
|
|
|
|
│ │ @AfterRet │ │ @Before │ │
|
|
|
|
|
|
│ │ @AfterThrow │ │ 数据权限过滤 │ │
|
|
|
|
|
|
│ └──────────────┘ └──────────────┘ │
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ┌──────────────┐ ┌──────────────┐ │
|
|
|
|
|
|
│ │ DataSource │ │ RateLimiter │ │
|
|
|
|
|
|
│ │ @Around │ │ @Before │ │
|
|
|
|
|
|
│ │ 多数据源切换 │ │ Redis 限流 │ │
|
|
|
|
|
|
│ │ Order(1) │ │ │ │
|
|
|
|
|
|
│ └──────────────┘ └──────────────┘ │
|
|
|
|
|
|
└─────────────────────────────────────────────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3.2 日志切面 (LogAspect)
|
|
|
|
|
|
|
|
|
|
|
|
| 属性 | 值 |
|
|
|
|
|
|
|------|-----|
|
|
|
|
|
|
| 触发方式 | `@annotation(Log)` |
|
|
|
|
|
|
| 通知类型 | `@AfterReturning`(成功)、`@AfterThrowing`(异常) |
|
|
|
|
|
|
| 记录内容 | 操作用户、IP、URL、方法名、请求参数、响应结果、业务类型、状态 |
|
|
|
|
|
|
| 写入策略 | **异步写入**(AsyncManager + AsyncFactory),不阻塞主线程 |
|
|
|
|
|
|
| 参数过滤 | 自动过滤 MultipartFile、HttpServletRequest 等不可序列化对象 |
|
|
|
|
|
|
|
|
|
|
|
|
### 3.3 数据权限切面 (DataScopeAspect)
|
|
|
|
|
|
|
|
|
|
|
|
| 属性 | 值 |
|
|
|
|
|
|
|------|-----|
|
|
|
|
|
|
| 触发方式 | `@annotation(DataScope)` |
|
|
|
|
|
|
| 通知类型 | `@Before` |
|
|
|
|
|
|
| 权限级别 | 5 种:全部(1)、自定义(2)、本部门(3)、本部门及以下(4)、仅本人(5) |
|
|
|
|
|
|
| 实现原理 | 在查询参数 `params.dataScope` 中注入 SQL 片段,XML 中通过 `${params.dataScope}` 拼接 |
|
|
|
|
|
|
| 安全机制 | 执行前先清空 `dataScope` 参数防止 SQL 注入 |
|
|
|
|
|
|
|
|
|
|
|
|
**SQL 拼接示例**:
|
|
|
|
|
|
```sql
|
|
|
|
|
|
-- 本部门权限
|
|
|
|
|
|
AND (d.dept_id = 100)
|
|
|
|
|
|
-- 本部门及以下
|
|
|
|
|
|
AND (d.dept_id IN (SELECT dept_id FROM sys_dept WHERE dept_id = 100
|
|
|
|
|
|
OR find_in_set(100, ancestors)))
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3.4 数据源切面 (DataSourceAspect)
|
|
|
|
|
|
|
|
|
|
|
|
| 属性 | 值 |
|
|
|
|
|
|
|------|-----|
|
|
|
|
|
|
| 触发方式 | `@annotation(DataSource)` 或 `@within(DataSource)` |
|
|
|
|
|
|
| 通知类型 | `@Around` |
|
|
|
|
|
|
| 优先级 | `@Order(1)`(最高优先级) |
|
|
|
|
|
|
| 实现原理 | 通过 `ThreadLocal` 设置当前线程的数据源标识,执行完毕后清理 |
|
|
|
|
|
|
| 底层支持 | `DynamicDataSource`(继承 `AbstractRoutingDataSource`) |
|
|
|
|
|
|
|
|
|
|
|
|
### 3.5 限流切面 (RateLimiterAspect)
|
|
|
|
|
|
|
|
|
|
|
|
| 属性 | 值 |
|
|
|
|
|
|
|------|-----|
|
|
|
|
|
|
| 触发方式 | `@annotation(RateLimiter)` |
|
|
|
|
|
|
| 通知类型 | `@Before` |
|
|
|
|
|
|
| 存储介质 | Redis + Lua 脚本(原子操作) |
|
|
|
|
|
|
| 限流维度 | 默认(方法级)、IP(IP + 方法级) |
|
|
|
|
|
|
| 可配置参数 | `key`(键前缀)、`time`(时间窗口/秒)、`count`(最大请求数) |
|
|
|
|
|
|
| 默认值 | 60 秒内最多 100 次请求 |
|
|
|
|
|
|
| 失败响应 | 抛出 `ServiceException("访问过于频繁,请稍候再试")` |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 4. 模块依赖
|
|
|
|
|
|
|
|
|
|
|
|
### 4.1 模块依赖图
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
┌─────────────┐
|
|
|
|
|
|
│ ruoyi-admin │ ← 启动入口,打包部署
|
|
|
|
|
|
└──────┬──────┘
|
|
|
|
|
|
│
|
|
|
|
|
|
┌──────────────┼──────────────┐
|
|
|
|
|
|
▼ ▼ ▼
|
|
|
|
|
|
┌───────────┐ ┌───────────┐ ┌──────────────┐
|
|
|
|
|
|
│ruoyi- │ │ruoyi- │ │ ruoyi- │
|
|
|
|
|
|
│system │ │quartz │ │ generator │
|
|
|
|
|
|
└─────┬─────┘ └─────┬─────┘ └──────┬───────┘
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
▼ ▼ ▼
|
|
|
|
|
|
┌──────────────────────────────────────────┐
|
|
|
|
|
|
│ ruoyi-framework │
|
|
|
|
|
|
│ (Security, AOP, DataSource, Config) │
|
|
|
|
|
|
└────────────────────┬─────────────────────┘
|
|
|
|
|
|
│
|
|
|
|
|
|
┌──────────────┼──────────────┐
|
|
|
|
|
|
▼ ▼ ▼
|
|
|
|
|
|
┌───────────┐ ┌───────────┐ ┌──────────────┐
|
|
|
|
|
|
│book- │ │stock- │ │ ruoyi- │
|
|
|
|
|
|
│system │ │system │ │ common │
|
|
|
|
|
|
└─────┬─────┘ └─────┬─────┘ └──────┬───────┘
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
└──────────────┼───────────────┘
|
|
|
|
|
|
▼
|
|
|
|
|
|
(所有业务模块依赖)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 4.2 模块职责
|
|
|
|
|
|
|
|
|
|
|
|
| 模块 | 职责 | 核心内容 |
|
|
|
|
|
|
|------|------|----------|
|
|
|
|
|
|
| **ruoyi-admin** | 启动入口 & Controller 层 | SpringBoot 启动类、Controller、Swagger 配置 |
|
|
|
|
|
|
| **ruoyi-framework** | 框架核心 | Security 配置、JWT、AOP 切面、数据源、Redis、MyBatis 配置 |
|
|
|
|
|
|
| **ruoyi-system** | 系统管理业务 | 用户、角色、菜单、部门、字典、岗位、日志的 Service/Mapper/Domain |
|
|
|
|
|
|
| **ruoyi-common** | 通用工具 | 基类、工具类、注解、常量、异常、过滤器、分页组件 |
|
|
|
|
|
|
| **book-system** | 账务业务模块 | 账本、账户、操作记录、统计的 CRUD |
|
|
|
|
|
|
| **stock-system** | 股票业务模块 | 股票信息、行情、财务、趋势分析 |
|
|
|
|
|
|
| **ruoyi-quartz** | 定时任务 | 基于 Quartz 的任务调度 |
|
|
|
|
|
|
| **ruoyi-generator** | 代码生成 | 基于 Velocity 模板的代码生成器 |
|
|
|
|
|
|
|
|
|
|
|
|
### 4.3 技术栈汇总
|
|
|
|
|
|
|
|
|
|
|
|
| 分类 | 技术 | 版本 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| 核心框架 | Spring Boot | 2.5.8 |
|
|
|
|
|
|
| JDK | Java | 1.8 |
|
|
|
|
|
|
| 安全框架 | Spring Security + JWT | 内置 + jjwt 0.9.1 |
|
|
|
|
|
|
| ORM | MyBatis | 2.2.0 (spring-boot-starter) |
|
|
|
|
|
|
| 分页 | PageHelper | 1.4.0 |
|
|
|
|
|
|
| 数据库连接池 | Druid | 1.2.8 |
|
|
|
|
|
|
| 缓存 | Redis (Spring Data Redis) | 内置 |
|
|
|
|
|
|
| API 文档 | Springfox Swagger 3 | 3.0.0 |
|
|
|
|
|
|
| JSON | FastJSON | 1.2.79 |
|
|
|
|
|
|
| Excel | Apache POI | 4.1.2 |
|
|
|
|
|
|
| 验证码 | Kaptcha | 2.3.2 |
|
|
|
|
|
|
| 代码生成 | Velocity | 2.3 |
|
|
|
|
|
|
| 系统监控 | Oshi | 5.8.6 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 5. 存在的问题
|
|
|
|
|
|
|
|
|
|
|
|
| # | 问题 | 严重等级 | 影响范围 | 优化建议 |
|
|
|
|
|
|
|---|------|----------|----------|----------|
|
|
|
|
|
|
| 1 | **fastjson 版本存在已知漏洞** | 🔴 高 | 全系统 | fastjson 1.2.79 存在多个 CVE 漏洞(如 CVE-2022-25845),建议升级至 2.x(fastjson2)或替换为 Jackson/Gson |
|
|
|
|
|
|
| 2 | **使用已废弃的 WebSecurityConfigurerAdapter** | 🟡 中 | 安全配置 | Spring Security 5.7+ 已废弃 `WebSecurityConfigurerAdapter`,应改用 `SecurityFilterChain` Bean 配置方式 |
|
|
|
|
|
|
| 3 | **Token 解析异常被静默吞没** | 🟡 中 | 认证模块 | `TokenService.getLoginUser()` 中 catch 块为空(第 72-74 行),异常被完全忽略,建议至少记录 WARN 日志 |
|
|
|
|
|
|
| 4 | **SQL 注入风险:${params.dataScope}** | 🟡 中 | 数据权限层 | MyBatis XML 中 `${params.dataScope}` 使用 `${}` 直接拼接,虽有 DataScopeAspect 前置清空防护,但仍存在绕过风险;建议使用参数化方案或严格校验 |
|
|
|
|
|
|
| 5 | **业务 Controller 缺少 @Log 注解** | 🟢 低 | book-system | `book-system` 下的 Controller 中 `AccountController` 等部分接口缺少 `@Log` 操作日志注解,审计不完整 |
|
|
|
|
|
|
| 6 | **缺少统一 DTO/VO 分层** | 🟢 低 | 全系统 | Domain 实体直接暴露给 Controller 层(如 `SysUser` 同时用于数据库映射和接口响应),密码等敏感字段需额外处理;建议引入独立的 DTO/VO 对象 |
|
|
|
|
|
|
| 7 | **Service 层直接注入 Mapper(而非通过接口)** | 🟢 低 | 全系统 | `SysUserServiceImpl` 中使用 `@Autowired private SysUserMapper userMapper` 直接注入实现类,虽然 MyBatis 通过代理实现,但不符合面向接口编程原则 |
|
|
|
|
|
|
| 8 | **缺少接口版本控制** | 🟢 低 | API 设计 | 所有 API 路径无版本号(如 `/api/v1/system/user`),未来接口升级时无法平滑过渡 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
*文档结束*
|