若依脚手架详解一_项目结构_POI_RBAC
若依脚手架详解(一):项目结构、POI 与 RBAC
本章位置:第三阶段 Java 企业项目 + AI 助手
对应课程:使用 AI 了解若依脚手架(POI、RBAC)
前置知识:SpringBoot、Spring Security 基础、MyBatis、Redis、Vue3、Pinia、Vue Router、Axios、Git、RBAC
后续衔接:若依脚手架(二)Security、数据字典;淘车湾项目脚手架改造
学习目标:看懂若依项目结构、启动方式、登录认证链路、JWT/Token + Redis、动态菜单、菜单权限、按钮权限、用户角色权限表关系、数据权限基础,以及若依对 Apache POI Excel 导入导出的封装方式;掌握使用 Cursor / AI 阅读若依源码的方法。
一、若依是什么
若依:
RuoYi
可以理解为:
已经帮你搭好大量企业后台通用功能的开发脚手架
它不是:
一个业务系统
而是:
一个后台管理项目基础框架
你可以在它上面继续开发:
学生管理系统
商城后台
汽车维修系统
非遗管理平台
问答系统
审批系统
CRM
ERP 子系统
二、为什么企业项目喜欢脚手架
如果从空项目开始:
登录
权限
用户
角色
菜单
日志
分页
验证码
Redis
异常处理
文件上传
Excel
代码生成
全部自己写:
时间非常长
脚手架已经做好:
通用基础设施
你主要开发:
真正业务模块
三、若依已经帮你做了什么
常见内置模块:
用户管理
部门管理
岗位管理
角色管理
菜单管理
字典管理
参数管理
通知公告
操作日志
登录日志
在线用户
定时任务
代码生成
接口文档
服务监控
缓存监控
所以若依真正的价值是:
后台通用能力已经搭好
四、若依不是“复制代码就算会”
真正会若依需要理解:
登录怎么走
Token 存在哪里
Redis 怎么参与
权限怎么判断
菜单怎么动态生成
用户和角色怎么关联
角色和菜单怎么关联
按钮权限怎么生效
代码生成器生成了什么
Excel 导入导出怎么实现
五、当前若依版本体系
若依官方 RuoYi-Vue 文档目前提供多套后端分支:
master
Spring Boot 4.x
JDK 17+
springboot3
Spring Boot 3.x
JDK 17+
springboot2
Spring Boot 2.x
JDK 8+
前端也有:
RuoYi-Vue2
Vue2 + Element UI + Vue CLI + Vuex
RuoYi-Vue3
Vue3 + Element Plus + Vite + Pinia
RuoYi-Vue3-TypeScript
Vue3 + TypeScript
六、本课程推荐怎么学
你的学习栈已经是:
JDK 17
SpringBoot
Vue3
Vite
Pinia
Element Plus
所以阅读时建议优先:
后端:
RuoYi-Vue springboot3 分支
前端:
RuoYi-Vue3
这样和前面知识:
衔接最自然
七、为什么不直接从 master 开始
官方 master 当前可能使用:
更新的 Spring Boot 主版本
课程目标不是:
追最新版本号
而是:
看懂若依架构
Spring Boot 3:
对你当前 JDK17 和前面课程
更容易衔接
真正项目仍应:
按项目版本锁定依赖
八、RuoYi-Vue 和 RuoYi-Cloud 区别
RuoYi-Vue:
单体 / 模块化 SpringBoot 后台
RuoYi-Cloud:
微服务版本
当前课程第三阶段:
先学 RuoYi-Vue
第四阶段:
再进入若依 Cloud
九、后端顶层模块
经典 RuoYi-Vue 常见:
RuoYi-Vue
│
├─ ruoyi-admin
├─ ruoyi-common
├─ ruoyi-framework
├─ ruoyi-generator
├─ ruoyi-quartz
├─ ruoyi-system
├─ sql
└─ pom.xml
十、ruoyi-admin
它可以理解为:
后台应用启动模块
里面常见:
SpringBoot 启动类
Controller
application.yml
最终:
你启动的 Web 服务
通常从这里启动。
十一、ruoyi-system
负责:
系统核心业务
例如:
SysUser
SysRole
SysMenu
SysDept
SysPost
以及它们的:
Mapper
Service
Domain
十二、ruoyi-framework
负责:
框架级核心能力
常见:
Spring Security
Token
权限判断
Redis
数据权限
拦截器
全局 Web 配置
异步处理
十三、ruoyi-common
负责:
公共工具和公共模型
例如:
AjaxResult
BaseController
PageDomain
TableDataInfo
StringUtils
ServletUtils
ExcelUtil
@Excel
@Log
异常类
十四、ruoyi-generator
负责:
代码生成
输入:
数据库表
生成:
Entity/Domain
Mapper
Mapper XML
Service
Controller
Vue 页面
API
SQL 菜单
十五、ruoyi-quartz
负责:
定时任务
基于:
Quartz
如果项目完全不用定时任务:
可以按项目需要移除
十六、模块依赖思路
大概可以理解:
ruoyi-admin
↓
ruoyi-framework
↓
ruoyi-system
↓
ruoyi-common
具体 Maven 依赖:
看各模块 pom.xml
十七、为什么若依用 Maven 多模块
好处:
职责分离
公共代码复用
模块可插拔
业务边界清晰
又回到你学过的:
Maven 多模块
十八、前端目录
RuoYi-Vue3 常见思路:
src
│
├─ api
├─ assets
├─ components
├─ directive
├─ layout
├─ plugins
├─ router
├─ store
├─ utils
├─ views
├─ App.vue
├─ main.js
└─ permission.js
不同版本:
目录细节可能变化
但职责基本一致。
十九、api
封装 HTTP 请求
例如:
api/login.js
api/system/user.js
api/system/role.js
api/system/menu.js
这和我们前面讲的:
API 层
完全一致。
二十、views
页面:
system/user
system/role
system/menu
二十一、store
Vue3 版本:
Pinia
保存:
用户
Token 相关状态
权限
动态路由
应用 UI 状态
二十二、router
负责:
基础路由
动态路由
页面导航
二十三、permission.js
非常关键。
它通常负责:
全局路由守卫
登录判断
动态路由加载
页面标题
白名单
后面读源码:
一定重点看
二十四、directive
若依会封装:
权限指令
例如:
v-hasPermi
v-hasRole
这就是前面自己学过的:
v-permission
的成熟实现。
二十五、先把若依启动起来
典型步骤:
1. 下载后端
2. 导入 SQL
3. 修改 MySQL
4. 修改 Redis
5. IDEA Maven Reload
6. 启动 ruoyi-admin
7. 下载前端 RuoYi-Vue3
8. 安装 npm/yarn/pnpm 依赖
9. 启动 Vite
10. 登录 admin
二十六、数据库
若依提供:
sql
目录。
通常:
先创建数据库
再执行官方初始化 SQL
二十七、为什么不要自己先建一堆表
若依核心:
sys_user
sys_role
sys_menu
关系:
已经设计好
学习时先:
按官方 SQL 运行
然后再分析。
二十八、启动后优先观察
不要马上:
写业务
先看:
用户管理
角色管理
菜单管理
部门管理
字典管理
日志
缓存监控
二十九、第一条源码阅读主线:登录
这是最重要主线。
前端:
Login Page
↓
login API
↓
后端 /login
↓
用户名密码认证
↓
生成 Token
↓
Redis
↓
返回 token
三十、登录后
前端保存 Token
↓
请求当前用户信息
↓
获得 roles + permissions
↓
请求动态路由
↓
后端构造菜单树
↓
前端注册动态路由
↓
进入首页
三十一、若依登录 Controller
经典源码中常见类名:
SysLoginController
可能包含:
/login
/getInfo
/getRouters
不同分支:
类签名可能稍有变化
但阅读链路基本相同。
三十二、/login
前端发送:
{
"username": "admin",
"password": "..."
}
后端:
SysLoginController
↓
SysLoginService
处理登录。
三十三、SysLoginService
主要职责:
校验验证码
校验用户名密码
AuthenticationManager 认证
加载 LoginUser
生成 Token
三十四、Spring Security AuthenticationManager
若依并没有自己从零写:
if password == databasePassword
而是利用:
Spring Security
认证体系。
三十五、UserDetailsService
Spring Security 会调用:
UserDetailsService
若依中常见:
UserDetailsServiceImpl
三十六、UserDetailsServiceImpl
核心:
根据 username
查询 SysUser
然后:
检查账号状态
获取权限
封装 LoginUser
三十七、LoginUser
非常关键。
可以理解为:
若依“当前已登录用户”的安全上下文对象
里面可能包含:
userId
deptId
SysUser
permissions
token
loginTime
expireTime
不同版本:
字段会变化
三十八、SysUser vs LoginUser
SysUser:
数据库用户业务对象
LoginUser:
认证后安全上下文对象
不要混淆。
三十九、登录为什么还要 Redis
若依使用:
Token + Redis
典型思想:
Token
只是客户端凭证
LoginUser
保存在 Redis
四十、Token 创建
通常:
生成随机 token 标识
LoginUser 写 Redis
设置过期时间
对外返回 JWT/Token
四十一、请求再次进来
浏览器:
Authorization: Bearer xxx
后端过滤器:
解析 Token
↓
Redis 获取 LoginUser
↓
放入 SecurityContext
四十二、所以若依 Token 和纯无状态 JWT 不完全一样
虽然使用:
JWT
但登录状态:
仍然和 Redis 中 LoginUser
有紧密关系
四十三、这样有什么好处
可以:
主动注销
在线用户管理
刷新过期时间
踢用户下线
多实例共享登录状态
四十四、TokenService
这是阅读登录链路必须看的类。
职责通常包括:
创建 Token
获取 LoginUser
设置 LoginUser
刷新 Token
删除登录状态
验证有效期
四十五、Redis Key
若依会给登录用户:
设计专门的 Redis Key 前缀
你要重点理解:
Token 中的标识
如何映射到 Redis LoginUser
不要只背具体字符串。
四十六、登录链路总图
Vue Login
↓
POST /login
↓
SysLoginController
↓
SysLoginService
↓
AuthenticationManager
↓
UserDetailsServiceImpl
↓
SysUserService
↓
MyBatis
↓
sys_user
↓
LoginUser
↓
TokenService
↓
Redis
↓
Token
↓
Vue
四十七、第二条源码阅读主线:当前用户
登录成功后:
/getInfo
用于获取:
user
roles
permissions
四十八、为什么不能只依赖登录接口返回所有东西
刷新页面以后:
前端 Pinia 重建
所以需要:
通过 Token
重新获取当前用户
这和前面 Vue 企业后台章节:
/auth/me
完全一个思想。
四十九、权限集合从哪里来
大致:
userId
↓
查询角色
↓
查询菜单权限标识
↓
permissions Set
五十、若依中的权限标识
例如:
system:user:list
system:user:add
system:user:edit
system:user:remove
system:user:export
system:user:import
五十一、权限码结构
推荐理解:
模块:资源:动作
例如:
system:user:add
意思:
system 模块
user 资源
add 动作
五十二、不要把权限码和 URL 混淆
URL:
/system/user/list
权限:
system:user:list
它们:
可以相关
但不是一个概念
五十三、第三条源码阅读主线:动态菜单
前端请求:
/getRouters
后端:
根据当前用户
查询有权菜单
然后:
构建菜单树
返回前端。
五十四、动态菜单为什么来自后端
不同角色:
看到不同菜单
例如:
管理员:
系统管理
用户管理
角色管理
菜单管理
普通用户:
个人中心
业务模块
五十五、后端菜单到前端路由
流程:
sys_menu
↓
后端查询用户菜单
↓
树结构
↓
RouterVo
↓
JSON
↓
前端 store
↓
filterAsyncRouter
↓
动态 import
↓
router.addRoute
类名:
按具体分支查看
五十六、这和我们前面学的动态路由完全对应
我们自己设计:
component = system/user/index
若依:
也是类似思想
所以你现在再读:
若依动态路由
会容易很多。
五十七、RBAC 是若依最核心的数据库关系
先记住核心表:
sys_user
sys_role
sys_menu
sys_user_role
sys_role_menu
五十八、sys_user
保存:
用户
例如:
admin
zhangsan
lisi
五十九、sys_role
保存:
角色
例如:
超级管理员
普通角色
财务
运营
六十、sys_menu
非常重要。
它不仅存:
左侧菜单
还可以存:
目录
菜单
按钮权限
六十一、sys_user_role
用户与角色:
多对多关系表
例如:
user 1001
→ role 1
user 1001
→ role 2
六十二、sys_role_menu
角色与菜单/权限:
多对多关系表
六十三、RBAC 核心链路
User
↓
sys_user_role
↓
Role
↓
sys_role_menu
↓
Menu / Permission
六十四、为什么按钮也在 sys_menu
若依将:
目录
菜单
按钮
统一作为:
菜单权限资源
管理。
这会让角色授权树:
一次把页面和按钮权限一起配置
六十五、菜单类型
经典若依一般有:
M
目录
C
菜单
F
按钮
具体字段值:
以当前 SQL 为准
六十六、目录
例如:
系统管理
主要作用:
组织子菜单
六十七、菜单
例如:
用户管理
对应:
一个前端页面路由
六十八、按钮
例如:
新增用户
修改用户
删除用户
导出
通常:
不生成路由页面
而是:
提供 permission 标识
六十九、角色授权
管理员勾选:
用户管理
├─ 查询
├─ 新增
├─ 修改
├─ 删除
└─ 导出
保存:
sys_role_menu
七十、用户最终 permissions
登录后:
user
↓
roles
↓
menus/buttons
↓
permission String Set
七十一、后端接口权限
若依经典 Spring Security 方式:
@PreAuthorize(
"@ss.hasPermi('system:user:list')"
)
七十二、@ss 是什么
它代表:
Spring 容器中的权限判断 Service
经典类名常见:
PermissionService
七十三、hasPermi
作用:
当前登录用户
是否拥有指定权限字符串
七十四、示例
@PreAuthorize(
"@ss.hasPermi('system:user:add')"
)
@PostMapping
public AjaxResult add(
@RequestBody SysUser user
) {
...
}
七十五、角色判断
例如:
@PreAuthorize(
"@ss.hasRole('admin')"
)
七十六、权限优先还是角色优先
业务接口更常:
permission code
因为:
角色会变化
权限能力更具体
不要在每个 Controller 写:
if admin
七十七、前端按钮权限
经典:
<el-button
v-hasPermi="[
'system:user:add'
]"
>
新增
</el-button>
七十八、后端和前端必须一致
前端:
system:user:add
后端:
system:user:add
数据库:
system:user:add
三处:
必须一致
七十九、前端隐藏按钮是否安全
不安全。
因为用户可以:
Postman
curl
直接访问接口。
真正安全:
@PreAuthorize
后端校验。
八十、这和前面自己写 RBAC 的结论完全一致
前端权限
负责体验
后端权限
负责安全
八十一、超级管理员
若依对:
超级管理员
通常有:
特殊全权限逻辑
不会逐个权限码普通判断。
八十二、不要在自己的业务里到处写 userId == 1
若依内部可能有:
isAdmin
统一判断。
你的业务代码:
应该复用框架能力
八十三、sys_dept
若依还有:
部门
用于组织结构:
公司
↓
部门
↓
小组
八十四、sys_role_dept
角色:
数据权限
可能会和:
部门
建立关系。
八十五、功能权限 vs 数据权限
功能权限:
你能不能点击“用户查询”
数据权限:
你能查询哪些用户
八十六、例子
A 和 B 都有:
system:user:list
A:
能看全部部门
B:
只能看自己部门
这就是:
同一个功能权限
不同数据范围
八十七、若依数据权限
若依框架中有:
数据权限处理
典型:
根据角色 dataScope
给 SQL 添加部门/用户过滤条件
八十八、本章只需要建立基础
数据权限完整源码:
后面第二篇继续深入
现在先记:
RBAC 不只是按钮
八十九、登录和权限总图
username/password
↓
Spring Security
↓
LoginUser
↓
Token
↓
Redis
↓
后续 Request
↓
SecurityContext
↓
@PreAuthorize
↓
PermissionService
↓
LoginUser.permissions
↓
Allow / 403
九十、动态菜单总图
Current User
↓
User Roles
↓
Role Menus
↓
sys_menu
↓
Menu Tree
↓
getRouters
↓
Vue Pinia
↓
Dynamic Routes
↓
Sidebar
九十一、POI 是什么
Apache POI:
Java 操作 Office 文档的库
常见:
Excel
Word
PowerPoint
若依主要使用它处理:
Excel 导入导出
九十二、为什么企业后台非常常用 Excel
例如:
用户导入
学生名单导入
商品批量导入
订单导出
日志导出
统计报表
九十三、如果自己纯 POI 写会怎样
你需要处理:
Workbook
Sheet
Row
Cell
类型转换
日期格式
表头
样式
枚举转换
字典转换
图片
异常
每个模块都写:
非常重复
九十四、若依怎么封装
若依提供:
@Excel
ExcelUtil<T>
把大量重复 POI 操作:
封装起来
九十五、@Excel
在实体字段:
@Excel(
name = "用户名称"
)
private String userName;
表示:
这个字段参与 Excel
列标题:
用户名称
九十六、常用 @Excel 参数
常见:
name
sort
dateFormat
dictType
readConverterExp
separator
cellType
width
prompt
具体:
以当前版本注解定义为准
九十七、name
@Excel(
name = "用户名称"
)
Excel 表头:
用户名称
九十八、dateFormat
@Excel(
name = "登录时间",
dateFormat = "yyyy-MM-dd HH:mm:ss"
)
private Date loginDate;
九十九、readConverterExp
例如:
@Excel(
name = "性别",
readConverterExp =
"0=男,1=女,2=未知"
)
private String sex;
把:
数据库值
转换为:
Excel 可读文字
一百、dictType
若依有:
数据字典
例如:
@Excel(
name = "帐号状态",
dictType =
"sys_normal_disable"
)
private String status;
Excel 导出时:
根据字典转换显示
一百零一、这就是 POI 和数据字典的连接
Database Value
0 / 1
↓ dictType
Excel
正常 / 停用
下一篇:
会详细讲数据字典
一百零二、ExcelUtil
典型:
ExcelUtil<SysUser> util =
new ExcelUtil<>(
SysUser.class
);
它会通过:
反射
扫描:
@Excel
字段。
一百零三、这里和前面 Java 反射联系起来了
若依:
读取字段注解
↓
反射获取属性
↓
生成 Excel Cell
所以你前面学:
反射 + 注解
不是白学。
一百零四、Excel 导出接口
若依经典示意:
@Log(
title = "用户管理",
businessType =
BusinessType.EXPORT
)
@PreAuthorize(
"@ss.hasPermi('system:user:export')"
)
@PostMapping("/export")
public void export(
HttpServletResponse response,
SysUser user
) {
List<SysUser> list =
userService
.selectUserList(
user
);
ExcelUtil<SysUser> util =
new ExcelUtil<>(
SysUser.class
);
util.exportExcel(
response,
list,
"用户数据"
);
}
不同后端分支:
可能使用 GET/POST
或不同返回方式
思路一致。
一百零五、导出流程
点击导出
↓
Vue
↓
/system/user/export
↓
@PreAuthorize
↓
查询 User List
↓
ExcelUtil<SysUser>
↓
反射 @Excel
↓
Apache POI
↓
HttpServletResponse
↓
浏览器下载 xlsx
一百零六、为什么导出也必须有权限
数据导出:
可能比页面查询风险更高
因为用户可以:
一次下载大量数据
所以:
system:user:export
必须单独控制。
一百零七、前端导出按钮
Vue:
<el-button
v-hasPermi="[
'system:user:export'
]"
@click="handleExport"
>
导出
</el-button>
一百零八、前端 handleExport
若依通常封装:
download()
例如:
handleExport() {
proxy.download(
"system/user/export",
{
...queryParams.value
},
`user_${Date.now()}.xlsx`
)
}
不同 Vue2 / Vue3 版本:
写法会不同
一百零九、下载为什么不能按普通 JSON 处理
Excel 响应:
二进制文件
前端需要:
Blob / 下载工具
若依已经:
封装好
一百一十、导入流程
用户选择 xlsx
↓
el-upload
↓
POST multipart/form-data
↓
MultipartFile
↓
ExcelUtil.importExcel
↓
List<SysUser>
↓
业务校验
↓
批量插入/更新
↓
返回导入结果
一百一十一、导入接口示意
@PostMapping("/importData")
public AjaxResult importData(
MultipartFile file,
boolean updateSupport
) throws Exception {
ExcelUtil<SysUser> util =
new ExcelUtil<>(
SysUser.class
);
List<SysUser> userList =
util.importExcel(
file.getInputStream()
);
String operName =
getUsername();
String message =
userService.importUser(
userList,
updateSupport,
operName
);
return success(
message
);
}
实际类名和辅助方法:
按当前分支为准
一百一十二、为什么导入不能直接 Mapper batch insert
因为 Excel 数据:
不可信
必须业务校验:
用户名重复
手机号格式
部门是否存在
字段是否为空
状态是否合法
数据字典是否合法
一百一十三、updateSupport
典型意义:
如果用户已经存在
是否允许更新
一百一十四、为什么不能默认覆盖
批量 Excel:
很容易误覆盖数据
所以前端:
让用户明确选择
一百一十五、导入模板
若依支持:
下载 Excel 模板
帮助用户:
按正确列格式填写
一百一十六、模板接口
思路:
ExcelUtil<SysUser> util =
new ExcelUtil<>(
SysUser.class
);
return util.importTemplateExcel(
"用户数据"
);
具体当前版本可能:
直接写 HttpServletResponse
一百一十七、为什么模板非常重要
没有模板:
用户自己猜 Excel 列
错误率:
非常高
一百一十八、导入前端
典型:
el-upload
需要携带:
Authorization Bearer Token
因为:
导入接口同样受认证保护
一百一十九、上传 Header
思路:
headers: {
Authorization:
"Bearer "
+ getToken()
}
一百二十、为什么普通 Axios 拦截器可能管不到 el-upload
有些上传组件:
自己发请求
所以需要:
显式配置 headers
或者:
使用 http-request
自己通过统一 request 封装上传
一百二十一、导入 Excel 的事务
如果一批:
100 个用户
第 80 个失败:
前 79 个要不要保留?
需要:
明确业务策略
一百二十二、方案一:全有全无
@Transactional
任何一条失败:
整批 rollback
适合:
强一致导入
一百二十三、方案二:部分成功
每一条:
单独验证
最后返回:
成功 90
失败 10
失败原因
适合:
运营批量导入
一百二十四、若依用户导入更偏什么
若依常见实现:
逐条处理
统计成功/失败
返回信息
阅读源码时重点看:
importUser()
不要只看 Controller。
一百二十五、POI 导入最常见错误
Excel 列不匹配
日期格式错误
数字被解析成科学计数
空 Cell
字典值错误
超大文件内存问题
一百二十六、大 Excel 为什么危险
传统 POI:
一次把大量 Workbook 数据加载到内存
几十万行:
可能耗费大量 Heap
一百二十七、大文件怎么办
可以考虑:
流式读取
EasyExcel
分批处理
若依官方文档也有:
EasyExcel 集成示例
但当前课程:
先把内置 ExcelUtil 学明白
一百二十八、不要为了“性能”第一天就替换若依 ExcelUtil
如果你的毕业设计:
只有几百/几千行
内置能力:
通常足够
时间有限:
先完成业务
一百二十九、@Log
若依导出接口常看到:
@Log(
title = "用户管理",
businessType =
BusinessType.EXPORT
)
这个注解作用:
记录操作日志
一百三十、@Log 怎么实现
大致:
@Log
↓
AOP
↓
LogAspect
↓
记录请求/操作
↓
写操作日志
又回到前面:
AOP + 注解 + 反射
一百三十一、一个 Controller 为什么那么多框架能力
例如:
@PreAuthorize
@Log
@PostMapping
分别:
Spring Security
权限
若依 AOP
日志
Spring MVC
HTTP 路由
一百三十二、这就是企业框架组合
一个方法:
不只是一段 Java
它同时处在:
Web
Security
AOP
Transaction
MyBatis
Redis
多个框架体系中。
一百三十三、BaseController
若依 Controller 经常:
extends BaseController
它提供很多通用方法:
startPage()
getDataTable()
success()
error()
toAjax()
一百三十四、startPage()
用于:
分页参数处理
通常和:
PageHelper
配合。
一百三十五、典型列表
@GetMapping("/list")
public TableDataInfo list(
SysUser user
) {
startPage();
List<SysUser> list =
userService
.selectUserList(
user
);
return getDataTable(
list
);
}
一百三十六、为什么 startPage 必须在查询前
PageHelper 常通过:
ThreadLocal
保存当前分页参数。
然后下一条 MyBatis 查询:
自动应用分页
一百三十七、如果查询前做了别的 SQL
可能:
分页作用到错误 SQL
所以:
startPage 后尽快执行目标查询
一百三十八、TableDataInfo
统一分页返回。
通常包含:
rows
total
code
msg
前端表格:
直接使用
一百三十九、AjaxResult
若依统一响应对象。
用于:
success
error
data
这和我们前面自定义:
Result<T>
一个思想。
一百四十、toAjax()
常见:
return toAjax(
service.insert(...)
);
把:
影响行数
转换:
成功/失败响应
一百四十一、读若依不能只看“好方便”
你需要问:
这个方便方法底层做了什么?
例如:
startPage
要追:
BaseController
↓
TableSupport
↓
PageHelper
一百四十二、若依 CRUD Controller 基本模板
/list
GET
/{id}
GET
/
POST
/
PUT
/{ids}
DELETE
/export
POST
/importData
POST
一百四十三、权限码基本模板
system:xxx:list
system:xxx:query
system:xxx:add
system:xxx:edit
system:xxx:remove
system:xxx:export
system:xxx:import
一百四十四、代码生成器为什么厉害
给数据库表:
sys_student
可以生成:
SysStudent
SysStudentMapper
SysStudentMapper.xml
ISysStudentService
SysStudentServiceImpl
SysStudentController
Vue API
Vue Page
Menu SQL
一百四十五、是不是生成后不用看代码
绝对不是。
生成代码:
只是 CRUD 基线
业务:
仍然需要你改
一百四十六、AI + 代码生成器的正确关系
代码生成器:
生成稳定 CRUD 骨架
AI:
理解业务
修改字段
增加逻辑
重构交互
排错
一百四十七、不要让 AI 从零重写若依已有功能
例如:
若依已经有 TokenService
不要让 AI 又创建:
JwtUtil
LoginInterceptor
RedisTokenManager
形成:
第二套认证体系
一百四十八、这是用 Cursor 改若依最大的坑
AI 不知道现有框架:
已经做了什么
如果提示词只说:
“给我实现 JWT 登录”
它会:
重新实现一套
一百四十九、正确 AI 提示词
当前项目基于官方 RuoYi-Vue springboot3 分支。
请先阅读现有:
SysLoginController
SysLoginService
TokenService
SecurityConfig
PermissionService
要求:
复用若依现有登录和权限体系,
不要新增第二套 JWT、
不要新增自定义登录拦截器、
不要替换 LoginUser。
一百五十、让 AI 开发业务模块
例如:
维修预约
提示:
使用若依现有 BaseController、AjaxResult、TableDataInfo、
@PreAuthorize、@Log、分页工具和代码风格。
权限前缀:
repair:appointment:*
不要修改若依核心认证代码。
一百五十一、若依源码阅读方式 1:按入口追
不要:
从第一个文件开始读到最后
而是:
选择一个功能
按调用链追
一百五十二、登录阅读路线
前端 Login
↓
api/login
↓
/login
↓
SysLoginController
↓
SysLoginService
↓
AuthenticationManager
↓
UserDetailsServiceImpl
↓
TokenService
↓
Redis
一百五十三、权限阅读路线
Controller @PreAuthorize
↓
@ss
↓
PermissionService
↓
SecurityContext
↓
LoginUser
↓
permissions
一百五十四、菜单阅读路线
/getRouters
↓
SysMenuService
↓
sys_menu
↓
buildMenus
↓
RouterVo
↓
Vue Store
↓
router.addRoute
一百五十五、Excel 阅读路线
Controller export
↓
ExcelUtil
↓
@Excel
↓
Reflection
↓
Apache POI
↓
Response
一百五十六、分页阅读路线
Controller startPage
↓
PageHelper
↓
Mapper
↓
SQL
↓
TableDataInfo
一百五十七、日志阅读路线
@Log
↓
LogAspect
↓
AsyncManager
↓
SysOperLog
↓
Database
不同版本:
异步实现细节可能变化
一百五十八、IDEA 快捷阅读
Ctrl + 点击:
进入定义
一百五十九、Alt + F7
IDEA:
Find Usages
查看:
一个方法在哪里被使用
一百六十、Ctrl + Alt + B
常用于:
跳转到实现
例如接口:
ISysUserService
跳:
SysUserServiceImpl
一百六十一、Ctrl + N
快速找:
Class
例如:
TokenService
一百六十二、Ctrl + Shift + N
快速找:
File
例如:
SysUserMapper.xml
一百六十三、Ctrl + Shift + F
全局搜索:
system:user:list
这是读若依非常好用的方式。
一百六十四、搜索一个权限码能看到什么
搜索:
system:user:export
你可能同时找到:
SQL 菜单
Controller @PreAuthorize
Vue v-hasPermi
瞬间把:
数据库
后端
前端
串起来。
一百六十五、这是强烈推荐的学习方法
看到:
permission code
就全局搜索。
一百六十六、搜索一个 URL
例如:
/system/user/list
可以串:
Vue API
↓
Controller
↓
Service
↓
Mapper
一百六十七、Cursor 阅读大型项目
可以先让 Cursor:
列出模块职责
但必须:
引用真实文件
不要接受:
凭空总结
一百六十八、AI 阅读第一步
要求:
不要修改任何文件
只分析
例如:
请只阅读当前 RuoYi 项目,不要修改代码。
请分析登录链路,
必须列出真实类名、方法名和文件路径,
从前端 login 请求一直追踪到 Redis Token 保存。
一百六十九、第二步
让 AI:
画调用链
例如:
A.method
→ B.method
→ C.method
一百七十、第三步
让 AI 解释:
每层职责
而不是:
逐行翻译代码
一百七十一、第四步
让 AI 标出:
哪些是若依核心代码
哪些是业务扩展点
一百七十二、为什么这个问题重要
你以后改项目:
尽量改业务扩展点
不要:
乱改 TokenService
SecurityConfig
PermissionService
否则:
框架核心容易被破坏
一百七十三、业务模块放哪里
可以新增:
ruoyi-xxx
业务 Maven 模块。
例如:
ruoyi-repair
一百七十四、也可以放 system 吗
小毕业设计:
可以
但业务越来越多:
单独 module
更清楚。
一百七十五、淘车湾项目更适合
例如:
ruoyi-business
或按业务:
ruoyi-repair
具体:
课程项目结构决定
一百七十六、不要第一天拆 20 个 Maven 模块
毕业设计:
规模有限
过度模块化:
只增加开发成本
一百七十七、若依自定义业务表
例如:
CREATE TABLE biz_student (
student_id BIGINT PRIMARY KEY,
student_name VARCHAR(50),
status CHAR(1)
);
一百七十八、为什么推荐 biz_ 前缀
和:
sys_
框架系统表区分。
不是强制:
但非常清楚
一百七十九、不要随便改 sys_user 表塞几十个业务字段
例如学生业务:
学院
专业
学号
积分
全部塞:
sys_user
会让:
认证系统表和业务表强耦合
一百八十、更合理
sys_user
负责账号身份
biz_student
负责学生业务资料
通过:
user_id
关联。
一百八十一、角色表也一样
不要把:
所有业务规则
全塞:
sys_role
Role:
负责权限身份
一百八十二、若依权限表关系练习
假设:
张三
角色:运营
运营角色
拥有:
商品查询
商品新增
商品修改
数据库:
sys_user
张三
sys_role
运营
sys_user_role
张三 → 运营
sys_menu
product:list
product:add
product:edit
sys_role_menu
运营 → 三个权限
一百八十三、张三登录后
UserDetailsService
↓
查询 permissions
↓
LoginUser.permissions
=
[
product:list,
product:add,
product:edit
]
一百八十四、张三请求删除
接口:
@PreAuthorize(
"@ss.hasPermi('product:remove')"
)
LoginUser:
没有 product:remove
结果:
403
一百八十五、前端
删除按钮:
v-hasPermi="[
'product:remove'
]"
所以:
按钮也不显示
一百八十六、但即使前端被改
用户手动调用:
DELETE
后端仍:
403
这才完整。
一百八十七、角色和菜单修改后缓存
用户登录时:
permissions
已经放在:
LoginUser / Redis
如果管理员修改角色权限:
旧登录会话是否立即变化
需要看:
若依对应版本的刷新/清理策略
一百八十八、为什么这是 Redis + RBAC 结合点
权限信息:
不仅在数据库
运行时可能:
还在 Redis LoginUser
所以权限变更:
需要考虑缓存一致性
一百八十九、在线用户
若依能够管理:
在线用户
正是因为:
登录会话存在 Redis
可以:
列出
强退
一百九十、强退的本质
删除:
目标 LoginUser Redis Key
用户下一个请求:
Token 找不到有效登录状态
然后:
重新登录
一百九十一、验证码
若依登录页常有:
验证码
验证码答案:
临时存 Redis
并设置:
TTL
又和上一章 Redis:
完全连接起来
一百九十二、为什么学习顺序合理
你先学:
Redis Token
验证码
动态路由
RBAC
现在看若依:
就不是魔法
只是:
成熟项目把这些功能组合起来
一百九十三、POI 权限设计
常见:
xxx:import
xxx:export
和:
xxx:list
分开。
一百九十四、为什么 list 权限不等于 export
查询页面:
每次只看 10 条
Export:
可能导出数万条
数据风险:
更高
一百九十五、Excel 导出也要数据权限
即使有:
system:user:export
还应该:
只导出当前用户允许的数据范围
一百九十六、关键点
导出数据来源:
userService.selectUserList(user)
应该复用:
正常数据权限 SQL
不能:
导出时写一个 select * 绕过 DataScope
一百九十七、这就是功能权限 + 数据权限
Export Permission
决定能不能导
Data Scope
决定能导哪些
一百九十八、Excel 导入安全
导入文件来自:
用户
必须当作:
不可信输入
检查:
文件类型
文件大小
字段长度
必填字段
业务唯一性
字典值
权限
一百九十九、不要只看文件后缀
.xlsx:
只是文件名
真正安全:
还要解析验证
毕业设计:
至少做基础限制
二百、导入数量限制
不要让用户:
一次上传 100 万行
可以:
限制文件大小
限制记录数量
二百零一、导出数量也要限制吗
有些企业系统:
会限制
因为大导出:
耗内存
耗数据库
请求超时
二百零二、大导出高级方案
异步任务
分页读取
流式写出
OSS 下载
当前若依入门:
先使用内置 ExcelUtil
二百零三、ExcelUtil 和代码生成的关系
代码生成器可以生成:
导出 Controller
然后自动引用:
ExcelUtil
@Excel
所以:
POI 能力已经进入生成模板
二百零四、为什么生成代码里字段上有 @Excel
因为生成器:
根据数据库字段配置
生成:
Excel 注解
二百零五、生成后一定要检查
例如:
密码
身份证
Secret
内部字段
不应该:
自动导出
要删除:
@Excel
或调整导出对象。
二百零六、强烈推荐单独 ExportVO
复杂系统:
不要直接 SysUser Entity 导出所有字段
可以:
UserExportVO
只放:
允许导出的列
二百零七、为什么更安全
白名单:
明确哪些字段能出去
而不是:
实体新增字段后
不小心一起导出
二百零八、POI 与 Bean/反射
若依 ExcelUtil 的思想:
JavaBean
↓
反射 Field
↓
读取 @Excel
↓
读/写属性
↓
Excel Cell
这串知识你前面都学过。
二百零九、POI 与泛型
ExcelUtil<SysUser>
使用:
泛型
告诉工具:
操作哪种 JavaBean
二百一十、POI 与注解
@Excel
属于:
元数据
ExcelUtil:
读取注解参数
决定:
列名
格式
字典
排序
二百一十一、为什么若依是很好的综合学习项目
它把:
JavaBean
反射
注解
AOP
SpringBoot
Spring Security
MyBatis
Redis
Vue
Router
Pinia
POI
Maven
全部:
连接在真实项目
二百一十二、第一次读若依不要改什么
暂时不要:
重写 SecurityConfig
替换 TokenService
替换 LoginUser
改 sys_user 主键机制
改权限表达式
换整个响应结构
二百一十三、先改什么
推荐:
新增一个简单业务模块
例如:
学生管理
二百一十四、学生管理练习
数据库:
biz_student
字段:
student_id
student_name
student_no
college
major
status
二百一十五、代码生成器
导入表:
biz_student
配置:
模块名
业务名
权限前缀
包名
生成:
CRUD
二百一十六、导入生成 SQL
代码生成会给:
菜单 SQL
执行后:
后台菜单出现学生管理
二百一十七、为什么菜单没出现
常见:
菜单 SQL 没执行
角色没授权
重新登录前权限缓存没刷新
component path 错
二百一十八、为什么按钮没出现
检查:
sys_menu perms
角色菜单关联
/getInfo permissions
前端 v-hasPermi
二百一十九、为什么按钮有但接口 403
说明:
前端权限状态
和后端当前权限状态
不一致
检查:
Redis LoginUser
数据库角色权限
权限码拼写
二百二十、为什么接口能调但按钮没有
可能:
后端权限已更新
前端 permissions 还旧
或:
v-hasPermi 拼写错
二百二十一、若依权限问题排查顺序
1. sys_menu.perms 对不对
2. sys_role_menu 有没有关系
3. 用户有没有 role
4. /getInfo 返回 permissions 有无目标码
5. 前端 v-hasPermi 是否一致
6. Controller @PreAuthorize 是否一致
7. Redis 登录缓存是否旧
二百二十二、登录失败排查顺序
1. 后端是否启动
2. MySQL 是否连通
3. Redis 是否连通
4. 验证码
5. 用户是否存在
6. 用户状态
7. 密码
8. Security 日志
9. TokenService
二百二十三、401 排查
Token 没带
Bearer 格式错误
Token 过期
Redis LoginUser 不存在
Token 解析失败
二百二十四、403 排查
已经登录
但是 Permission 不满足
重点:
/getInfo permissions
@PreAuthorize
二百二十五、404 排查
前端 API URL
Controller @RequestMapping
Vite proxy
动态路由 component
后端 context-path
二百二十六、Excel 下载失败
检查:
导出接口权限
请求方法
download 封装
Response Content-Type
后端异常
数据查询
二百二十七、Excel 导入 401
常见:
el-upload 没带 Authorization
二百二十八、Excel 导入 403
说明:
有登录
但没有 import permission
二百二十九、Excel 导入数据失败
检查:
@Excel
列名
数据格式
importUser 业务校验
唯一约束
事务
二百三十、如何让 Cursor 帮你排若依问题
错误提示词:
若依报错了,帮我修
太模糊。
二百三十一、正确提示词
当前是官方 RuoYi-Vue springboot3 + RuoYi-Vue3。
问题:
用户管理导入返回 403。
请只分析,不修改。
请检查:
1. 前端导入按钮权限码
2. upload Authorization Header
3. Controller @PreAuthorize
4. sys_menu perms
5. 当前 LoginUser permissions
必须引用真实文件路径和方法。
二百三十二、为什么这样 AI 更可靠
你把问题限制为:
一个调用链
AI 不会:
到处重构
二百三十三、若依核心文件建议阅读清单
登录:
SysLoginController
SysLoginService
UserDetailsServiceImpl
TokenService
二百三十四、Security
SecurityConfig
JwtAuthenticationTokenFilter
AuthenticationEntryPointImpl
LogoutSuccessHandlerImpl
具体类名:
按分支可能变化
二百三十五、权限
PermissionService
SysPermissionService
SysMenuService
二百三十六、系统模型
SysUser
SysRole
SysMenu
SysDept
LoginUser
二百三十七、通用 Web
BaseController
AjaxResult
TableDataInfo
二百三十八、Excel
@Excel
@Excels
ExcelUtil
二百三十九、日志
@Log
LogAspect
BusinessType
二百四十、Redis
RedisCache
CacheConstants
TokenService
二百四十一、前端
api/login
store/modules/user
store/modules/permission
router
permission.js
directive/permission
Vue3 分支具体目录:
以实际源码为准
二百四十二、第一天阅读不要超过这些
否则:
文件太多
容易:
失去主线
二百四十三、三条核心主线足够
登录
权限
Excel
掌握以后:
再扩展
二百四十四、若依 RBAC 总关系图
SysUser
│
│ sys_user_role
↓
SysRole
│
│ sys_role_menu
↓
SysMenu
│
├─ M 目录
├─ C 菜单
└─ F 按钮
↓
perms
二百四十五、若依认证总关系图
Browser
↓
Login
↓
Spring Security
↓
UserDetailsService
↓
LoginUser
↓
TokenService
↓
Redis
下一请求
↓
Bearer Token
↓
Authentication Filter
↓
Redis LoginUser
↓
SecurityContext
二百四十六、若依后端权限总关系图
Controller
↓
@PreAuthorize
↓
@ss.hasPermi
↓
PermissionService
↓
SecurityContext
↓
LoginUser
↓
permissions Set
↓
true / false
二百四十七、若依前端权限总关系图
/getInfo
↓
permissions
↓
Pinia
↓
v-hasPermi
↓
Button Visible
二百四十八、动态路由总关系图
/getRouters
↓
SysMenuService
↓
Menu Tree
↓
RouterVo
↓
Vue Permission Store
↓
Dynamic Route
↓
Sidebar
二百四十九、Excel 总关系图
JavaBean
↓
@Excel
↓
Reflection
↓
ExcelUtil<T>
↓
Apache POI
↓
XLSX
导入:
XLSX
↓
POI
↓
ExcelUtil
↓
JavaBean List
↓
Service Validation
↓
MySQL
二百五十、若依最值得你学的不是 UI
而是:
工程组织
例如:
统一响应
统一分页
统一权限
统一日志
统一异常
统一 Redis
统一 Excel
统一代码生成
二百五十一、统一能力为什么重要
如果每个业务模块:
自己写一套
最后:
代码风格不一致
Bug 难排
权限容易漏
维护成本高
二百五十二、脚手架思维
业务开发者应该:
站在框架能力上开发
不是:
绕开框架重新造轮子
二百五十三、什么时候应该修改若依核心
只有:
真正的全局需求
例如:
整个项目换认证模式
全局统一响应结构改变
全局权限模型改变
才考虑。
二百五十四、普通业务需求
例如:
学生新增一个手机号字段
不应该:
修改 SecurityConfig
二百五十五、业务隔离原则
框架核心
尽量稳定
业务模块
持续变化
二百五十六、Git 使用建议
第一次下载若依:
git checkout -b feature/business
二百五十七、改框架前
git status
git add .
git commit -m "chore: baseline ruoyi project"
二百五十八、AI 改动前
再做 checkpoint
因为若依:
文件非常多
AI 一次改坏:
很难手工恢复
二百五十九、不要提交生产 Secret
包括:
MySQL Password
Redis Password
JWT Secret
OSS Secret
二百六十、若依配置文件
开发学习:
可以用本地开发配置
真正提交仓库:
应避免真实生产密钥
二百六十一、POI 安全练习
给 User 实体:
password
千万不要:
@Excel(name="密码")
二百六十二、密码永远不应该导出
数据库存的也应该:
Hash
不是:
明文
二百六十三、身份证/手机号导出
取决于:
权限和业务
可能需要:
脱敏
二百六十四、若依也有数据脱敏能力
下一阶段可继续了解。
二百六十五、Excel Formula Injection
如果导出用户输入:
=...
+...
-...
@...
某些电子表格软件可能:
当公式执行
复杂系统需要:
对不可信文本做导出安全处理
毕业设计至少:
知道这个风险
二百六十六、上传 Excel 文件名也不可信
不要:
直接拿原文件名拼服务器路径
若依导入通常:
直接读取流
更简单。
二百六十七、批量导入密码怎么处理
例如:
用户 Excel 导入
不要让 Excel:
提供明文最终密码
可以:
系统生成默认密码
首次登录强制修改
具体:
按项目业务
二百六十八、导入用户权限
能导入用户:
不代表能导入管理员
业务 Service:
应该限制危险角色赋值
二百六十九、不要信任 Excel 中 roleId
用户上传:
roleId=1
不应该:
直接变超级管理员
二百七十、这就是“文件输入也是外部输入”
和 HTTP JSON:
一样需要校验
二百七十一、若依学生模块综合练习
目标:
Student CRUD
+
RBAC
+
Excel
二百七十二、数据库
CREATE TABLE biz_student (
student_id BIGINT NOT NULL AUTO_INCREMENT,
user_id BIGINT,
student_no VARCHAR(50) NOT NULL,
student_name VARCHAR(50) NOT NULL,
college VARCHAR(100),
major VARCHAR(100),
status CHAR(1) DEFAULT '0',
create_by VARCHAR(64),
create_time DATETIME,
update_by VARCHAR(64),
update_time DATETIME,
remark VARCHAR(500),
PRIMARY KEY (student_id),
UNIQUE KEY uk_student_no (student_no)
);
二百七十三、为什么加 create_by/create_time
若依很多业务表:
会使用审计字段
配合:
BaseEntity
更方便。
二百七十四、生成代码
导入:
biz_student
生成模块:
system/student
或者:
business/student
权限前缀:
business:student
二百七十五、权限
business:student:list
business:student:query
business:student:add
business:student:edit
business:student:remove
business:student:export
business:student:import
二百七十六、Student Excel 字段
@Excel(name = "学号")
private String studentNo;
@Excel(name = "姓名")
private String studentName;
@Excel(name = "学院")
private String college;
@Excel(name = "专业")
private String major;
二百七十七、不要导出
例如:
内部 userId
如果业务页面不需要:
可以不标 @Excel
二百七十八、学生导出
查询条件
↓
DataScope
↓
List<Student>
↓
ExcelUtil
↓
XLSX
二百七十九、学生导入
XLSX
↓
List<Student>
↓
校验学号唯一
↓
校验学院/专业
↓
插入
二百八十、给普通角色授权
例如:
student_manager
只勾:
list
query
add
edit
import
export
不给:
remove
二百八十一、验证前端
登录 student_manager:
删除按钮
不显示
二百八十二、验证后端
Postman:
DELETE /business/student/1
应该:
403
二百八十三、这就是完整 RBAC 验证
不是:
只看菜单
二百八十四、完整练习步骤
1. 启动 MySQL
2. 启动 Redis
3. 初始化若依数据库
4. 启动 ruoyi-admin
5. 启动 RuoYi-Vue3
6. admin 登录
7. 查看用户/角色/菜单
8. 创建 biz_student
9. 代码生成
10. 执行菜单 SQL
11. 导入生成代码
12. 新增 student_manager 角色
13. 分配部分权限
14. 创建普通用户
15. 测试 CRUD
16. 测试按钮权限
17. Postman 测试 403
18. 加 @Excel
19. 测试导出
20. 测试导入
21. 测试 updateSupport
22. 检查操作日志
二百八十五、学习目标验收 1
你应该能说清:
ruoyi-admin
ruoyi-framework
ruoyi-system
ruoyi-common
分别干什么。
二百八十六、学习目标验收 2
能画出:
/login
完整调用链。
二百八十七、学习目标验收 3
能解释:
LoginUser
为什么不是普通 SysUser。
二百八十八、学习目标验收 4
能解释:
Token
为什么和 Redis 有关系
二百八十九、学习目标验收 5
能解释:
/getInfo
返回什么。
二百九十、学习目标验收 6
能解释:
/getRouters
为什么能生成不同菜单。
二百九十一、学习目标验收 7
能画:
sys_user
↓
sys_user_role
↓
sys_role
↓
sys_role_menu
↓
sys_menu
二百九十二、学习目标验收 8
能解释:
M/C/F
为什么按钮也放 sys_menu。
二百九十三、学习目标验收 9
能解释:
@PreAuthorize
+
@ss.hasPermi
二百九十四、学习目标验收 10
能解释:
v-hasPermi
只是前端体验权限。
二百九十五、学习目标验收 11
能说明:
@Excel
如何配合:
ExcelUtil + Reflection + POI
二百九十六、学习目标验收 12
能自己实现:
Excel 导入/导出
而不是只会点按钮。
二百九十七、高频面试题 1
问:
若依是什么?
答:
若依是一套开源的企业后台快速开发脚手架。
它基于 SpringBoot、Spring Security、MyBatis、Redis、
前端 Vue 等技术,
内置用户、角色、菜单、权限、日志、代码生成、
Excel、定时任务等常见后台能力。
业务项目可以在这些通用能力之上继续开发。
二百九十八、面试题 2
问:
若依主要模块分别做什么?
答:
ruoyi-admin:
Web 启动和 Controller。
ruoyi-system:
用户、角色、菜单、部门等系统业务。
ruoyi-framework:
Security、Token、Redis、数据权限等框架核心。
ruoyi-common:
公共工具、统一响应、Excel、注解等。
ruoyi-generator:
代码生成。
ruoyi-quartz:
定时任务。
二百九十九、面试题 3
问:
若依登录流程?
答:
前端提交用户名密码到 /login。
后端通过 Spring Security 的认证体系加载用户,
封装 LoginUser,
然后 TokenService 创建 Token,
把登录状态保存到 Redis,
最后把 Token 返回前端。
后续请求携带 Token,
认证过滤器解析并从 Redis 恢复 LoginUser,
再放入 SecurityContext。
三百、面试题 4
问:
为什么若依还用 Redis 保存 LoginUser?
答:
这样可以管理服务器端登录状态,
支持 Token 过期刷新、主动注销、在线用户、
踢人下线以及多实例共享登录状态等能力。
三百零一、面试题 5
问:
若依 RBAC 主要有哪些表?
答:
sys_user
sys_role
sys_menu
sys_user_role
sys_role_menu
用户和角色多对多,
角色和菜单/权限多对多。
三百零二、面试题 6
问:
sys_menu 为什么既保存菜单又保存按钮?
答:
若依把目录、页面菜单和按钮权限统一抽象成系统权限资源。
菜单节点用于生成页面导航,
按钮节点主要提供 permission code,
角色授权时可以在一棵权限树中统一配置。
三百零三、面试题 7
问:
@PreAuthorize("@ss.hasPermi(...)") 怎么工作?
答:
Spring Security 在方法执行前解析 @PreAuthorize 表达式。
@ss 指向若依的权限判断 Service,
它从当前 SecurityContext/LoginUser 中读取用户权限集合,
判断指定 permission code 是否存在。
没有权限时接口不会进入正常业务方法。
三百零四、面试题 8
问:
v-hasPermi 有什么作用?
答:
前端根据当前用户 permissions
决定按钮是否显示。
它主要用于用户体验,
不能替代后端 @PreAuthorize,
因为用户可以绕过前端直接调用 API。
三百零五、面试题 9
问:
/getInfo 和 /getRouters 区别?
答:
/getInfo 主要返回当前用户、角色和权限集合。
/getRouters 主要根据当前用户可访问菜单
构建动态路由树返回前端。
前者解决“我是谁、我有什么权限”,
后者解决“我能看到哪些页面入口”。
三百零六、面试题 10
问:
若依 Excel 导出怎么实现?
答:
JavaBean 字段使用 @Excel 描述列信息。
Controller 查询需要导出的业务数据,
创建 ExcelUtil<T>,
ExcelUtil 通过反射读取 @Excel 配置,
底层使用 Apache POI 构建 Excel,
再通过 HttpServletResponse 返回文件。
三百零七、面试题 11
问:
为什么 Excel 导入必须做业务校验?
答:
Excel 属于外部输入,不能直接信任。
导入后需要校验必填字段、格式、唯一性、
字典值、关联数据和当前用户权限,
再决定插入或更新。
不能解析出 JavaBean List 后直接全部写数据库。
三百零八、面试题 12
问:
功能权限和数据权限区别?
答:
功能权限决定用户是否能调用某个功能,
例如 system:user:list。
数据权限决定已经拥有查询功能后,
具体能看到哪些数据,
例如全部部门、当前部门或本人数据。
三百零九、面试题 13
问:
BaseController 的作用?
答:
若依把常见 Web Controller 公共能力放在 BaseController 中,
例如 startPage、getDataTable、success、error、toAjax 等,
从而减少业务 Controller 的重复代码。
三百一十、面试题 14
问:
startPage 为什么要放查询之前?
答:
PageHelper 通常在当前线程保存分页参数,
下一次 MyBatis 查询会读取分页信息并改写分页 SQL。
因此 startPage 后应尽快执行目标列表查询,
否则分页可能作用到错误 SQL。
三百一十一、面试题 15
问:
如何用 AI 改若依更安全?
答:
先要求 AI 阅读现有若依核心类,
明确真实文件和调用链,
并要求复用现有 Token、Security、Redis、权限、统一响应和分页体系。
普通业务开发不要让 AI 再创建一套 JWT、
一套权限拦截器或另一套响应结构。
修改前使用 Git 建立 checkpoint,
修改后逐文件检查 diff。
三百一十二、若依第一部分知识树
RuoYi
│
├─ Backend Modules
│ ├─ ruoyi-admin
│ ├─ ruoyi-framework
│ ├─ ruoyi-system
│ ├─ ruoyi-common
│ ├─ ruoyi-generator
│ └─ ruoyi-quartz
│
├─ Auth
│ ├─ SysLoginController
│ ├─ SysLoginService
│ ├─ AuthenticationManager
│ ├─ UserDetailsService
│ ├─ LoginUser
│ ├─ TokenService
│ └─ Redis
│
├─ RBAC
│ ├─ sys_user
│ ├─ sys_role
│ ├─ sys_menu
│ ├─ sys_user_role
│ └─ sys_role_menu
│
├─ Permission
│ ├─ @PreAuthorize
│ ├─ @ss.hasPermi
│ ├─ v-hasPermi
│ └─ Dynamic Router
│
├─ Web
│ ├─ BaseController
│ ├─ AjaxResult
│ ├─ TableDataInfo
│ └─ PageHelper
│
├─ Excel
│ ├─ Apache POI
│ ├─ @Excel
│ ├─ ExcelUtil
│ ├─ Import
│ └─ Export
│
└─ AI Development
├─ Read First
├─ Follow Call Chain
├─ Reuse Framework
├─ Avoid Duplicate Auth
└─ Git Checkpoint
三百一十三、必须记住的若依学习路线
不要:
一打开若依
就看几千个文件
按照:
1. 启动
2. 登录
3. Token
4. Redis
5. getInfo
6. getRouters
7. sys_user/sys_role/sys_menu
8. @PreAuthorize
9. v-hasPermi
10. ExcelUtil
11. 代码生成
12. 自己生成一个业务模块
三百一十四、本章最重要的一句话
若依不是:
“我不用学 SpringBoot 了”
而是:
“我已经学过的 SpringBoot、
Security、Redis、Vue、RBAC、AOP、MyBatis,
现在终于在一个成熟项目里组合起来了”
三百一十五、本章最终总结
若依核心模块:
ruoyi-admin
Web 入口
ruoyi-framework
框架核心
ruoyi-system
系统业务
ruoyi-common
公共能力
ruoyi-generator
代码生成
ruoyi-quartz
定时任务
认证:
/login
↓
Spring Security
↓
LoginUser
↓
TokenService
↓
Redis
↓
Token
权限:
User
↓
Role
↓
Menu/Permission
↓
LoginUser.permissions
↓
@PreAuthorize
前端:
/getInfo
↓
permissions
↓
v-hasPermi
/getRouters
↓
Dynamic Routes
↓
Sidebar
Excel:
@Excel
↓
Reflection
↓
ExcelUtil
↓
Apache POI
↓
XLSX
最重要的 RBAC 表:
sys_user
sys_role
sys_menu
sys_user_role
sys_role_menu
最重要的安全原则:
前端按钮隐藏不是安全
导入文件不能信任
导出也需要权限和数据范围
不要让 AI 重写第二套认证体系
不要随便修改若依框架核心
到这里,课程表中的:
使用 AI 了解若依脚手架
第一部分:POI + RBAC
完成。
下一篇继续:
《若依脚手架详解(二):Spring Security、数据字典与框架核心》
下一章重点:
SecurityFilterChain
JWT Authentication Filter
SecurityContext
LoginUser
Token 刷新
401 / 403
@Anonymous
PermissionService
数据权限 @DataScope
部门数据范围
数据字典
DictUtils
前端字典 useDict
防重复提交
操作日志
异常处理
XSS
若依核心代码正确改造方式
官方参考
若依官方文档:
https://doc.ruoyi.vip/ruoyi-vue/
项目结构:
https://doc.ruoyi.vip/ruoyi-vue/document/xmjs.html
后台手册:
https://doc.ruoyi.vip/ruoyi-vue/document/htsc.html
当前官方版本说明中:
后端提供 Spring Boot 2.x / 3.x / 4.x 分支
前端提供:
Vue2
Vue3 + Vite + Element Plus + Pinia
Vue3 + TypeScript
因此真正开发时:
必须先确定你使用的是哪个分支
不要混用:
Vue2 教程
Vue3 代码
Spring Boot 2 Security 配置
Spring Boot 3/4 API
课程学习以:
核心调用链和架构思想
为第一优先级。