简介:《ruoyi-vue-pro开发指南》以PDF格式打包,是一份面向RuoYi-Vue框架开发者的系统化技术文档,尤其适合需要快速搭建后台管理系统、理解前后端组件开发流程的Java全栈与Vue.js工程师。文档基于RuoYi-Vue重构优化后的项目展开,清晰划分系统功能、基础设施、工作流程、支付系统、数据报表、微信公众号等核心模块,并对新增功能使用🚀标记、重构功能使用⭐标记,便于读者按需查阅。内容覆盖用户权限、租户管理、代码生成、消息队列、分布式锁、在线用户监控、流程审批、支付订单等关键场景,不少页面还配有演示图,能帮助开发者减少踩坑、提升二次开发效率。资源为单文件PDF,大小约49.96MB,便于离线阅读和检索,已有4955人学习下载,适合正在使用或计划引入ruoyi-vue-pro的中高级开发者参考。
1. 把 RuoYi-Vue-Pro 当脚手架而不是源码:这份开发指南 PDF 解决什么问题
接手过几个中小型后台管理系统需求的人应该都有同感:用户、角色、菜单、部门、字典、日志、定时任务这些模块,每个项目都要重写一遍,写出来的东西还未必有人家开源框架严谨。RuoYi-Vue-Pro 是这类需求里被反复拿出来对比的前后端分离脚手架,Vue3 + Spring Boot,内置 RBAC 权限、代码生成、多租户和工作流。真正把它用好的人不多,大多数人卡在“能跑起来”和“能改第二处业务”之间。这份开发指南 PDF 的价值就是把框架的初始化、权限模型、代码生成、部署配置串成一条完整链路,让有 Spring Boot 基础的人直接跳到“改业务”这一步,而不是从零读源码。适合刚接触该框架的开发者,也适合要把老项目迁到该框架上的从业者。
2. 开发指南的整体脉络:先看清架构和边界,再决定从哪里读
2.1 四层代码结构与一次请求的完整流转链路
RuoYi-Vue-Pro 后端严格按经典分层在组织:Entity(实体层)、Mapper(数据访问层)、Service(业务层)、Controller(控制层)。第一次读这份 PDF 时别急着看代码,先把“一次请求怎么走的”这条链路画出来。
用户在前端页面上点击按钮,Vite 开发服务器把请求转发到后端 8080 端口的某个 Controller;Controller 收到请求后先做参数校验,然后调用 Service 层;Service 在注解事务内处理业务逻辑,通过 Mapper 操作 MySQL;Mapper 层基于 MyBatis Plus,自带逻辑删除和字段自动填充能力,返回值再逐层传回前端。
我一般会建议先看一个最简单的模块,比如“字典管理”,把 Controller、Service、Mapper、Entity 四个文件放在四个编辑器标签页里对照着读。PDF 里通常会把这种层间调用的关键代码贴出来,比你看源码仓库里的完整工程要省事得多。重点看 Service 实现类上那几个注解,事务注解和权限注解的搭配,是理解后续“为什么有些接口需要特定角色才能调”的基础。
2.2 前端与后端的接口契约:Vue3 项目里路由、API、状态管理怎么落位
前端这块 PDF 占的篇幅通常不小,毕竟 RuoYi-Vue-Pro 的定位是前后端分离。页面部分用的是 Vue3 组合式 API,构建工具是 Vite,UI 组件库以 Element Plus 为主。前端工程里跟业务直接相关的,是src/api目录下按模块拆分的接口定义文件,以及src/views目录下按菜单层级组织的页面组件。
我建议你在读 PDF 的接口联调章节时,对照着抓一次真实的登录请求。开发者工具里能看到浏览器发出的请求带上了/admin-api这样的前缀,后端网关或 Controller 接收到以后,从 Header 里取出 Token 做身份识别。前端工程里 axios 实例会在请求拦截器里统一加 Token,在响应拦截器里统一处理 401 状态码。这些机制在 PDF 里往往散落在不同章节,你可以自己串成一条线。
这样做的好处是后续接新模块时,你不需要等后端接口全部写完再动前端。先照着契约文件把 API 函数名、请求方法、参数结构约定好,前后端并行开发,联调时冲突会少很多。
2.3 PDF 里不会明说、但你必须知道的技术选型边界
读这类项目文档时,很多人容易忽略版本边界。RuoYi-Vue-Pro 不同时期的分支差异比较明显,后端 JDK 版本、Spring Boot 版本、前端 Node 版本、MyBatis Plus 版本都可能不同,PDF 里写的示例配置未必直接适用于你下载的源码包。
关键是要在开头就核对三组信息:JDK 是 8 还是 17 及以上,Spring Boot 是 2.x 还是 3.x,前端工程是用 Vue3 的 Options API 还是 Composition API 风格。这三个基础项决定你后面抄配置时要不要微调。例如 Spring Boot 3.x 下spring.redis的配置前缀改成了spring.data.redis,直接照抄 2.x 的配置会导致启动时静默失效,Redis 连接在第一个登录请求时才报错。
我一般会把 PDF 里的技术栈清单抄出来,列成一张表,标注“文档默认版本”和“我本机使用版本”两列,逐项核对完再动手。这个习惯能省掉后面至少两个小时的排错时间。
| 技术组件 | 典型版本区间 | 需要核对的关键点 |
|---|---|---|
| JDK | 8 / 17 | Spring Boot 3.x 必须用 17 |
| Spring Boot | 2.7 / 3.x | Redis 配置前缀、javax 与 jakarta 命名空间 |
| Vue | 3.x | 是否使用 setup 语法糖 |
| Vite | 4/5 | Node 版本要求 |
| MyBatis Plus | 3.5.x | 逻辑删除、自动填充的全局配置 |
| MySQL | 5.7 / 8.x | 字符集、时区参数 |
3. 按指南把项目跑起来:环境准备、配置修改、前后端联调三件事
3.1 环境准备:JDK、MySQL、Redis 的最小组合与版本陷阱
PDF 的第一大章节基本都会讲环境准备,这也是新手翻车最多的地方。先明确结论:最小可运行组合是 JDK + MySQL + Redis 三个服务,缺一个都起不来后端。前端只需要 Node 环境和包管理器,npm 和 pnpm 都行。
MySQL 初始化时要注意字符集必须包含 utf8mb4,排序规则选 utf8mb4_unicode_ci 或 utf8mb4_general_ci 均可,但前后要一致。我遇到过数据库建好后默认 latin1 的,登录接口返回中文乱码,排查了半天才发现是库表字符集问题。Redis 方面,Windows 环境可以下载官方提供的压缩包启动红版,或者用 Docker 跑。
# 以 Docker 方式准备 MySQL 和 Redis,本地开发最快的一种方式 docker run -d --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=123456 \ mysql:8.0 docker run -d --name redis7 \ -p 6379:6379 \ redis:7-alpine两个容器都映射到了本机默认端口。密码设置成了 123456,仅限本地开发用。如果你本机 3306 或 6379 已经被占用,可以改容器端口映射,比如-p 3307:3306,相应地后端配置文件里的 datasource url 也要改成对应端口。这里有一个容易忽略的细节:MySQL 8 默认的认证插件是 caching_sha2_password,老版本驱动连接时会报错。后端项目里带的驱动如果是 8.x,基本没问题;如果是 5.7 时代的驱动与 MySQL 5.7 的组合,记得在连接串上确认 useSSL=false 和 serverTimezone=Asia/Shanghai。
3.2 后端启动参数:配置文件里的必改项与建议项
后端配置文件通常是application.yaml或application-local.yaml。PDF 里一般会强调“先跑默认配置”,但实际上最省事的做法是新建一份自己的配置,用--spring.profiles.active=local启动。
# application-local.yaml 中的核心配置片段 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/ruoyi_vue_pro?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver redis: host: 127.0.0.1 port: 6379 database: 0 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0上面这段里最关键的是logic-delete-field: deleted。RuoYi-Vue-Pro 的多数表都带 deleted 字段做逻辑删除,MyBatis Plus 全局配置开启后,所有 Mapper 的查询会自动拼接deleted = 0,不需要你在每个 XML 或注解里手动加。log-impl建议开发期间开着 SQL 日志,能直接看到 MyBatis Plus 生成的 SQL,排查多租户和数据权限问题时尤其有用。上线之前再把这个配置关掉,避免刷日志。
另外 MongoDB、消息队列、文件存储这些中间件的配置项,PDF 里通常给了 default 值但不会实际使用。如果你只跑核心功能,可以先全部注释掉,减少启动依赖。等业务真正用到时再按官方文档逐步打开,这个策略能让你把注意力集中在框架主链路上。
3.3 前端跑通:Vite proxy 与登录请求链路
前端工程跑起来之前,先确认 Node 版本满足 Vite 要求。Vue3 项目常见要求 Node 16 以上,新一点的版本建议 18 或 20。安装依赖时尽量用锁文件,npm ci 会严格按照 package-lock.json 安装,避免依赖版本漂移。
Vite 开发服务器默认跑在 5173 或 80 端口,关键是vite.config.ts里的 server.proxy 配置,它决定了开发环境下前端请求怎么转发到后端。
// vite.config.ts 中 proxy 配置常见写法 server: { port: 80, proxy: { '/admin-api': { target: 'http://127.0.0.1:8080', changeOrigin: true, pathRewrite: { '^/admin-api': '' } } } }这里changeOrigin: true必须保留,后端校验请求来源时依赖 Host 头。pathRewrite的作用是把 URL 里的/admin-api前缀剥掉再转发给后端。如果你发现登录请求能发出、但后端收到的是 404,优先检查这个 rewrite 规则是不是写对了。target 指向的端口要和后端实际启动端口一致,我见过有人后端改了端口只改了 target 的 IP,结果绕了一圈才发现端口漏了。
启动好前后端以后,打开浏览器访问前端页面,输入admin / admin123(具体账号以 PDF 或初始化 SQL 为准),看浏览器开发者工具里的 Network 面板。登录成功会返回 token,后续接口请求的 Header 里带了 token 且状态码是 200,说明链路已经通了。
4. 开发指南里最该精读的三块:权限模型、代码生成、多租户
4.1 权限数据模型:用户、角色、菜单、按钮之间的关系
RuoYi-Vue-Pro 的权限体系沿用了经典的 RBAC 模型:用户挂在角色下,角色关联菜单与按钮权限,菜单表里会区分目录、菜单、按钮三种类型。按钮也是一种“权限点”,前端控制按钮显隐,后端用注解校验。
// 权限注解的典型用法:需要在按钮级别控制访问权限 @PreAuthorize("@ss.hasPermission('system:user:create')") @PostMapping("/create") public CommonResult<Long> createUser(@Valid @RequestBody UserSaveReqVO createReqVO) { return success(userService.createUser(createReqVO)); }注解字符串里的system:user:create是权限标识,含义是“系统模块-用户管理-新增”。前端按钮上如果没配这个标识,请求也到不了这个接口,因为后端注解会拦截。注意不同版本的框架里权限校验注解的写法有差异,有的用@ss.hasPermission,有的兼容经典写法@ss.hasPermi,PDF 里通常会把本版本支持的两种都列出来,抄的时候以源码仓库为准。
读权限章节时,把登录用户的角色、菜单、按钮三层数据在数据库里查一遍,比干看文字更容易理解。你登录后能看到哪些菜单,本质上就是用户关联的角色所绑定的菜单树的子集。前端拿到用户信息时会返回一个权限标识数组,按钮的v-hasPermi指令用这个数组判断射不渲染。
4.2 代码生成器:从表结构到可运行 CRUD 的完整闭环
代码生成是这个框架最能节省时间的模块。PDF 会把操作流程拆成“导入表 - 配置字段 - 生成代码 - 下载解压 - 部署”五步。实际操作上,我更推荐先在数据库里把表设计好,包括字段注释、索引、是否允许为空,然后再去后端管理界面的代码生成菜单里导入这张表。
导入以后,关键操作是逐字段调整“列表、查询、表单”三个开关,以及每个字段的显示组件类型和校验规则。比如“创建时间”这种字段,在列表里需要展示,在表单里就不该出现;状态字段可以配成下拉框;备注字段可以配成文本域。生成代码会按这些配置产出前后端一整套文件。
生成后的产物通常是 zip 包,后端是 Controller、Service、Mapper、Entity、VO 等 Java 文件,前端是对应视图目录下的 index.vue 和 API 定义文件。解压以后按 PDF 说明放到对应目录,再编译一次。这里有个常见习惯问题:生成的代码只是“能跑”,不是“最优实现”。生成器生成的 Service 层逻辑偏简单,比如删除时可能没有做数据引用校验、导出功能没考虑大数据量。把它当起点,不要当终稿。
// 代码生成配置里常见的字段设置表示例 [ { "fieldName": "name", "fieldType": "string", "list": true, "query": true, "form": true, "queryType": "LIKE", "formComponent": "Input" }, { "fieldName": "status", "fieldType": "integer", "list": true, "query": false, "form": true, "formComponent": "Select", "dictType": "common_status" } ]这种配置是“通用型”的,所有框架的代码生成器逻辑都类似。name 字段会在列表和表单里都出现,查询方式走模糊查询;status 关联字典表渲染成下拉框,查询条件里不放它是因为状态不适合做筛选。实际业务字段多了以后,query开关只勾最常用的过滤条件,不然查询区会挤成一片。如果你生成的页面在提交表单时总是校验失败,回去检查这一步,多半是某个字段的“允许为空”配置和数据库约束不一致。
4.3 多租户和数据权限:这两层最容易理解偏差
多租户和数据权限是 RuoYi-Vue-Pro 相比经典若依增强最明显的两块。多租户解决的是“同一个系统给多个客户独立使用、数据隔离”的问题,数据权限解决的是“同一个租户内部不同角色看到不同范围数据”的问题。
多租户的常见实现方式是每张业务表加一个tenant_id字段,查询时框架自动拼接过滤条件。RuoYi-Vue-Pro 的租户模块会自动给新增数据填充当前租户 ID,读数据时自动加上租户过滤。这些逻辑对业务代码是透明的,但这正是隐患所在:如果你在某条 SQL 里手动写了联表查询,框架的 MyBatis Plus 拦截器可能不会自动处理tenant_id,导致跨租户数据泄露。
-- 一个典型的需要手工处理租户的联表查询 SELECT u.id, u.nickname, o.name FROM system_user u LEFT JOIN customer_order o ON o.user_id = u.id WHERE o.deleted = 0;这种写法里 MyBatis Plus 的租户插件可能只拦截主表,或者完全不拦截。正确做法是确认 PDF 里对应版本的租户拦截规则,必要时在 XML 里手写租户条件,或者用框架提供的 TenantUtils 工具显式声明忽略租户校验的合理场景(比如登录时校验账号密码,此时还不知道租户 ID)。我一般在联表查询优化时都会检查最终执行的 SQL,看看框架到底有没有帮你把 tenant_id 带上。把 SQL 日志和前端请求一一对上,是这个阶段最有效的验证手段。
5. 照着 PDF 复现时最容易踩的五个坑:现象、原因、解法
5.1 后端启动报错:报错堆栈定位不到根因
很多人在后端启动时遇到红色堆栈,第一反应是看最后几行异常描述,然后去搜索引擎复制粘贴,结果搜出来的方案跟自己的环境对不上。最典型的一个现象是启动时报Error creating bean with name 'redisTemplate',表面看是 Redis 连接失败,实际原因是 Redis 没启动、密码错误、或端口不对。
我的排查习惯是先确认三个前提进程:MySQL 和 Redis 是否有对应的端口监听,配置文件的 IP 端口密码是否和进程一致,防火墙是否放行本地端口。用telnet 127.0.0.1 6379能通,再去看启动日志。如果 Redis 装了但没设密码,配置文件里却配了 password,日志提示连接超时而不是认证失败。这三个前提排除以后,再去检查依赖版本。Spring Boot 3.x 用spring.data.redis前缀,写成了 2.x 的spring.redis时配置不生效,启动看起来成功,但登录时会报 Redis 序列化错误。这个坑很隐蔽,因为错误不在启动阶段暴露。
5.2 前端接口全部 404:proxy 转发路径对不上
登录页能打开,点登录按钮时所有请求都停在 Network 面板里,状态码是 404。不少人第一反应是后端接口没写对,实际上问题大概率在前端 proxy。
/admin-api这个前缀是统一约定的。前端发到/admin-api/system/auth/login,后端的接口路径实际是/system/auth/login。proxy 做了 pathRewrite 以后才能正确映射。常见的错误是:pathRewrite 配置了,但实际请求里前缀写成了/adminapi或者后端接口路径本身就带/admin-api,这时剥掉前缀反而找不到接口。拿 PDF 里前端的 axios 基地址、后端 Controller 的 RequestMapping 路径、vite proxy 的 rewrite 三段对照一遍,通常五分钟能锁死问题。
5.3 代码生成器生成后,前端菜单和按钮都不显示
生成完代码,后端编译通过,前端刷新页面却找不到新模块的菜单。这不是你代码放错位置,而是菜单数据没有初始化。RuoYi-Vue-Pro 的菜单是存在数据库里的,前端路由由后端动态返回,不是前端代码里静态写死的。
处理方式是到系统管理里的菜单管理中新增目录和新菜单,把前端路由地址、权限标识和组件路径填对。还有按钮权限点需要在菜单下配置按钮类型的权限记录,代码生成器产出的 ts 接口文件里有对应的权限标识,把每个按钮的标识逐条录入。这一步漏了的话,页面能看到,但点“新增”“编辑”按钮时后端会一直提示没有权限。跑这个流程时,看 PDF 里“菜单维护”章节对应的表结构,比你一个一个试快得多。
5.4 多租户数据串号:租户 1 看到了租户 2 的数据
现象是测试环境两个租户账号来回切换,偶尔能在列表里刷出别的租户数据,但复现很不稳定。原因通常是某个 Mapper 查询没走框架的租户拦截,或者手动 SQL 里没带 tenant_id 条件。MyBatis Plus 的租户插件对自定义 SQL 的支持是有限制的,复杂的联表、子查询、带别名的写法有时会被漏掉。
解决时先在 SQL 日志里搜tenant_id,逐条核对关键查询有没有过滤条件。日志里没有的,把这个 Mapper 方法拎出来改造成带租户条件的 SQL,或者找框架内提供的租户过滤工具方法。最容易被漏的是定时任务和异步线程里执行的 SQL,这些场景脱离了 Web 请求上下文,租户信息原本就丢,需要在任务入口手动设置租户上下文,执行完再清理。这条规则,我建议你在读 PDF 多租户章节时直接画成流程图贴在屏幕上。
5.5 文件上传后刷新页面就 404:本地存储路径不一致
上传附件成功,下载时却 404。这类问题通常是文件存储配置与访问映射对不上。RuoYi-Vue-Pro 支持本地存储或对象存储,本地模式下框架会把文件写到配置的目录里,再通过某个 URL 前缀映射到磁盘目录。
最常见的原因是 storage 配置里的路径是相对路径,比如./file,但实际工作目录跟你以为的目录不是同一个。启动脚本里没指定绝对路径,IDE 启动时工作目录可能是模块目录,打包部署后又变成了 jar 包所在目录。解决方法是把存储路径配成固定绝对路径,并在配置里对应好访问前缀。功能上能跑,不代表路径设计是对的。这个模块最好在自己机器上完整走一遍上传、下载、删除后再继续下一个模块。
6. 把 PDF 当成排查手册用:两个能提高效率的具体技巧
先说一个我常用的方法:拿到 PDF 以后不要从头开始读,先用检索工具把整本 PDF 的关键词位置拉出来,按模块建立索引。比如想看多租户实现,直接搜“租户”“tenant”,结果会列出所有相关小节的页码,对照过去快速扫一遍。Linux 环境下可以用 pdfgrep 这个命令行工具,Windows 上使用 PDF 阅读器自带的全局搜索功能效果类似。我会把每个大模块的起止页码记录在项目文档里,之后每次排查都先按这些页码翻,而不是盲目翻书。
# 在 PDF 里定位所有包含“租户”关键词的位置,输出页码、行号和各处摘录 pdfgrep -n "租户\|tenant" ruoyi-vue-pro开发指南.pdf这个方法比 PDF 阅读器搜索快,也方便批量导出。-n参数能输出所在页码,对几百页的技术文档来说这是最有价值的参数。搜出来以后,每个定位点都跳到上下文看一小段,判断是否和当前问题相关。例如搜“权限”,可能会定位到注解开发、菜单维护、数据权限三个不同的位置,它们的实现细节差异很大,趁这个机会把三者的边界弄清楚,远比只看目录里那个“权限管理”章节要全面。
第二个技巧是主动验证。PDF 里经常会出现“某某机制会自动处理”这样的描述,这类描述千万别直接信,要动手验证。打开后端的 SQL 日志,去执行一次对应功能,看日志里实际执行的 SQL 和 PDF 描述是否一致。比如 PDF 说“MyBatis Plus 会自动填充创建人、创建时间”,你就去观察插入语句里是不是真的带了这些字段。有次我验证自动填充逻辑时发现填充人和当前登录用户不一致,查了半天才发现框架里的用户上下文是在 Spring MVC 拦截器里设置的,我在一个异步线程里调用的接口根本没有拦截器经过,所以填充结果为空。从那以后我每次遇到框架自动特性,都强制走一遍“读文档描述 → 开启日志 → 实际操作 → 对照结果”的流程。这个过程会慢,但能避开最贵的一类坑:文档没问题、代码也没写错,只是在特殊场景下框架的自动行为没有按预期发生。希望你拿到这份 PDF 后也能带着这个习惯去读,遇到存疑机制就亲手验证一遍,把纸面知识落成你自己的调试经验。
本文还有配套的精品资源,点击获取