15 分钟跑起来
这一页的目标:从零把后端宿主和前端跑起来,然后装一个应用验证整条链路。
0. 准备环境
确认 JDK 17+、Maven 3.9+、Node 20+、MySQL 8.x、Redis 6+ 就绪,详见 环境要求。
如果你的 JDK / Maven 没加进 PATH,每个新终端先设一次:
$env:JAVA_HOME = "C:\Users\<you>\.jdks\corretto-17"
$mvn = "C:\path\to\maven\bin\mvn.cmd"后面所有命令都在 RuoYi-Vue-Plus 目录下执行。
1. 初始化数据库
按顺序导入 RuoYi-Vue-Plus/script/sql/ 下的脚本:
① platform_init.sql 平台表与平台数据
② update/app_market*.sql 应用市场表结构(按文件名顺序)
③ app_catalog_seed.sql 应用目录种子然后改 ruoyi-admin/src/main/resources/application-dev.yml 里的数据库与 Redis 连接。
2. 编译并打包后端
# 全反应堆编译(根 pom 默认 skipTests=true,编译不会跑测试)
& $mvn -B -q compile -DskipTests
# 打可运行 jar
& $mvn -pl ruoyi-admin -am -B install -DskipTests改了后端代码必须 install,不是 compile
只跑 mvn compile 不会更新 ruoyi-admin.jar,于是你启动的还是旧代码, 然后会得出"我的改动没生效"的错误结论,接着去改本来是对的代码。
3. 启动后端宿主
推荐用启动脚本 —— 它会先清理上一版插件 jar,再启动:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\start-host.ps1脚本可用参数:
powershell ... -File scripts\start-host.ps1 # 默认:清理 + 启动
powershell ... -File scripts\start-host.ps1 -Build # 先重新打包再启动
powershell ... -File scripts\start-host.ps1 -Port 8087 # 换端口
powershell ... -File scripts\start-host.ps1 -NoPlugin # 不加载插件(排查用)也可以手工启动:
java "-Dloader.path=plugins-dist" "-Dspring.profiles.active=prod" -jar ruoyi-admin\target\ruoyi-admin.jar-Dloader.path=... 的引号不能省
PowerShell 会把 -Dloader.path=plugins-dist 拆成 /path=plugins-dist, 报 ClassNotFoundException: /path=plugins-dist。两个 -D 参数都要加引号。
为什么要先清理旧的插件 jar
loader.path 不选版本 —— 它把 plugins-dist 下所有 jar 都挂上去。 同一个应用留下两个版本的 jar,就会有两份同样的 mapper XML, MyBatis 抛 Result Maps collection already contains value,服务直接起不来。
清理依据是部署时写下的 plugins-dist/active-plugins.txt: 只删同一个 appCode 名下非当前生效版本的 jar,手工放置的 jar 一律不碰。
4. 启动前端
cd plus-ui
npm install
npm run devdev server 在 80 端口,访问 http://localhost。
npm run dev 会自动先跑 gen:runtime 生成运行期垫片(predev 钩子),不用手动执行。
5. 登录
浏览器打开 http://localhost/login:
| 项 | 值 |
|---|---|
| 租户 | 000000 |
| 账号 | admin |
| 密码 | admin123 |
接口请求需要同时带 Authorization 与 clientid 两个头,缺一不可 —— 前端已经处理好,手工调接口时注意。
6. 装一个应用验证链路
登录后进入 应用市场:
- 在应用列表里挑一个应用(例如「图床管理」),点安装;
- 打开 我的应用 → 应用任务,看进度、步骤与日志 —— 这是排查问题的第一站, 步骤与日志是边跑边落库的,失败原因(含服务端异常文本)都在那里;
- 安装成功后,左侧菜单会出现这个应用的入口。
全程不需要重启后端。
一次安装实际发生了什么:
1. 生成 app_install_task 记录(任务中心就是看它)
2. 检查本机有没有产物
├─ 已有 → 就地使用(同一版本重装)
└─ 没有 / 正在升级 → 从市场按 packageUrl 下载
├─ 校验 MD5 / SHA256
├─ 安全检查:产物白名单 + 签名校验
├─ 解包落位:jar → plugin-dir 根下;前端 → frontend-dir/<appCode>/
└─ 记录 active-plugins.txt
3. 执行包内 migrations/*.sql(按文件名排序,幂等,只做 up)
4. 加载后端插件 ← 在迁移之后
5. 同步菜单与授权(按 app.json 的 menus 幂等 upsert)
6. 任务置为成功第 3 步在第 4 步之前是刻意设计的:先改表结构、再切换代码。 反过来的话,新代码在启动时机读一个还没建的列就会炸。
7. 跑测试
& $mvn -pl ruoyi-modules/ruoyi-app-market -B test "-DskipTests=false" "-Dprofiles.active=dev"新增测试必须打标签
根 pom 的 surefire 配了 <groups>${profiles.active}</groups>。 没打 @Tag("dev") / @Tag("local") / @Tag("prod") 的测试不会被执行 —— 看着全绿,其实没跑。
启动不起来?先看这四个
| 症状 | 原因 | 处理 |
|---|---|---|
Result Maps collection already contains value | plugins-dist 里同一应用有两个版本的 jar,MyBatis 解析了两份同样的 XML | 跑 scripts/prune-plugins.ps1(按 active-plugins.txt 只删非当前版本) |
| 插件完全没加载 | 只在 yml 里改了 app-market.plugin-runtime.enabled | 这个开关启动器读的是系统属性,必须用 JVM 参数 -Dapp-market.plugin-runtime.enabled=false 切换 |
expected single matching bean but found 2 | 宿主上下文里注册了与插件实现同类型的 bean | 见 插件运行时:宿主不能按类型注入插件 bean |
Failed to resolve component: KTable | 远程应用没有复刻宿主的组件解析器与白名单 | 见 前端远程应用 |
更多症状见 故障排查。
不要在别人正在跑的 JVM 上执行 mvn install
compiler 插件会先清空输出目录再全编。正在运行、按需懒解析类的 JVM 会抛 NoClassDefFoundError。这件事真实发生过。