若依脚手架详解一_项目结构_POI_RBAC

O泡李华 7

若依脚手架详解(一):项目结构、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

课程学习以:

核心调用链和架构思想

为第一优先级。