yudao-cloud 后端项目 · 命令行微服务部署笔记
环境基线(本次实操) :Windows · 代码目录
D:\yudao-code\yudao-cloud· MySQLroot / 123456· 数据库名固定ruoyi-vue-pro。范围说明 :第 1--5 章为本次实操验证过 的步骤;第 6--8 章为依据官方
quick-start文档整理的标准命令 (截至整理时尚未实操,命令以官方文档为准)。全流程一览 :环境核查 → 补装 Redis / Nacos → 建
dev命名空间 → 克隆代码 → 初始化 MySQL → 编译打包 → 启动 → 关闭。
1. 环境核查(一次性体检)
打开 cmd(Win+R → cmd),整段粘贴:
cmd
git --version
java -version
echo %JAVA_HOME%
mvn -v
mysql --version
redis-server --version
- 有版本号 = 已装;报「不是内部或外部命令」= 未装或未加 PATH。
- 本次核查结论:缺 Redis 与 Nacos,其余齐备 → 进入第 2、3 章补装。
- 注意:
mysql/redis命令找不到,也可能「已装但作为 Windows 服务在后台跑」(见第 2 章排错)。可在services.msc中确认服务状态。
2. 安装 Redis(Windows)
- 下载
Redis-x64-5.0.14.x.msi(GitHubtporadowski/redis或 Gitee 镜像mirrors/redis-windows)。 - 安装时务必勾选
Add the Redis installation folder to the PATH,一路 Next。 - 重开 cmd,验证:
redis-server --version出版本号即成功。
验证运行 :redis-cli ping 返回 PONG 即正常。
⚠️ 排错(本次实遇) :手动执行
redis-server报Could not create server TCP listening socket *:6379: bind: 在一个非套接字上尝试了一个操作。原因 :msi 安装时已把 Redis 注册为 Windows 服务并开机自启 ,6379 端口已被占用,无需再手动启动。 处理 :什么都不用做,直接redis-cli ping得PONG即可;可在services.msc看到 Redis 服务「正在运行 / 自动」。💡 答疑(本次实遇) :「之前
redis-server提示不是内部命令,现在怎么又能用了?」------之前尚未安装故找不到命令,安装并加 PATH 后即可识别,属正常。
3. 安装启动 Nacos 并建 dev 命名空间(Windows)
-
下载
nacos-server-2.x.zip(GitHubalibaba/nacosreleases),解压到无中文、无空格 路径,如D:\nacos-server-2.3.2\nacos。 -
启动(单机模式):
cmdcd /d D:\nacos-server-2.3.2\nacos\bin startup.cmd -m standalone末行出现
Nacos started successfully in stand alone mode即成功。 -
浏览器打开
http://127.0.0.1:8848/nacos。
⚠️ 答疑(本次实遇) :打开后没有登录页、直接进了控制台 ------因为默认未开启鉴权 ,免登录放行。这是正常且最省事的状态,切勿去开启鉴权(开了反而可能因账号密码对不上导致项目连不上 Nacos)。
-
建
dev命名空间(项目必需):左侧菜单「命名空间」→「新建命名空间」,按下表填写后确定:字段 填写 注意 命名空间ID dev必须手敲 dev,留空会生成 UUID 导致项目连不上命名空间名 dev同上 描述 任意 可不填 列表中出现
dev / dev一行即完成。
4. 克隆代码
选无中文无空格目录(本次为 D:\yudao-code):
cmd
D:
cd \yudao-code
git clone https://gitee.com/zhijiantianya/yudao-cloud.git
cd yudao-cloud
dir
- 成功标志:
dir列表含pom.xml与sql目录。 - 分支与 JDK 配对关系(编译前须核对):
master→ JDK 8 + Spring Boot 2.7;master-jdk17→ JDK 17/21 + Spring Boot 3.2。 - 容错:若该地址克隆失败或后续编译因缺模块报错,可将 clone 地址换为官方
https://gitee.com/yudaocode/yudao-cloud.git。
5. 初始化 MySQL
💡 答疑(本次实遇):
- 必须新建库;
- 库名固定为
ruoyi-vue-pro,不可改成带 yudao 的名字------配置文件写死,改名则启动时找不到库而报错。
cmd
:: 建库
mysql -u root -p123456 -e "CREATE DATABASE IF NOT EXISTS `ruoyi-vue-pro` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"
:: 验证(应列出几十张表)
mysql -u root -p123456 -e "USE `ruoyi-vue-pro`; SHOW TABLES;"
成功标志:SHOW TABLES 输出 system_*、infra_* 等几十张表,且无红色报错。
用 Navicat 初始化 yudao 本地数据库(图形化,替代命令行)
适用:本地 MySQL 已装好(
root/123456,端口3306)。本质就两步------建一个空库 → 把ruoyi-vue-pro.sql导进去 。与命令行CREATE DATABASE+mysql ... < file.sql完全等价,只是用鼠标点。
前提:Navicat 里要有连本地 MySQL 的连接
左侧若已有连到 127.0.0.1 的连接,跳过。没有就建:
连接 → MySQL → 主机 127.0.0.1、端口 3306、用户名 root、密码 123456 → 测试连接(提示成功)→ 确定。
2.2 建空库
- 左侧右键该连接 → 新建数据库。
- 填:
| 项 | 值 |
|---|---|
| 数据库名 | ruoyi-vue-pro |
| 字符集 | utf8mb4 |
| 排序规则 | utf8mb4_general_ci(或 utf8mb4_unicode_ci,均可) |
- 确定。左侧出现
ruoyi-vue-pro(先别展开,里面是空的)。
2.3 导入 SQL 文件
- 右键刚建的库
ruoyi-vue-pro→ 运行 SQL 文件。 - 弹窗里:
- 文件 :点
...选D:\yudao-code\yudao-cloud\sql\mysql\ruoyi-vue-pro.sql(路径以你实际 clone 位置为准,文件在sql\mysql目录下,只导这一个,同目录若有别的 .sql 不要选)。 - 编码 :
UTF-8(默认一般对;若导完中文乱码,回来改成65001 (UTF-8)重导)。
- 文件 :点
- 点 开始。
- 下方日志滚动,别中途关窗口 ;跑完出现
[Msg] Finished - Successfully(或"完成")→ 点 关闭。
2.4 刷新 + 验证(不刷新会以为没导进去)
- 右键库
ruoyi-vue-pro→ 刷新 (或选中库按 F5)。← 关键,导完左边树不自动刷新。 - 展开 表 ,应有几十张表 (
system_users、system_role、infra_*等)。 - 双击打开
system_users,应能看到admin那一行 → 初始化成功。
导完即可按之前流程起后端、admin / admin123 登录验证。
6. 编译打包(mvn 命令行)
6.1 确认 JDK 与分支配对
项目有两条分支,JDK 版本必须配对,否则编译直接报错:
| 分支 | 对应 JDK | Spring Boot |
|---|---|---|
master |
JDK 8 | 2.7 |
master-jdk17 |
JDK 17 / 21 | 3.2 |
检查当前状态:
cmd
cd /d D:\yudao-code\yudao-cloud
java -version
git branch
mvn -v
重点看 mvn -v 输出中的 Java version 那一行------这才是编译时真正生效的 JDK。
踩坑记录: 本机装的是 JDK 17,但克隆后默认在
master分支(需要 JDK 8),直接编译会报一堆看不懂的错。解决: 切到
master-jdk17分支即可,不用换 JDK:
cmdgit checkout master-jdk17 git branch确认输出中
* master-jdk17带星号即切换成功。
6.2 指定 Maven 配置文件
本机存在多份 settings.xml(公司内网、阿里云等),Maven 默认读取 C:\Users\32804\.m2\settings.xml。若该文件配的是公司内网仓库,编译会走内网地址,需要用 -s 参数显式指定要用的配置文件。
先确认目标配置文件里确实有阿里云镜像:
cmd
type D:\Maven_Public\settings.xml | findstr aliyun
输出中应包含 https://maven.aliyun.com/repository/public。
踩坑记录: 未加
-s参数,编译走了公司内网http://10.200.164.226:8081/...,手动Ctrl+C中止。解决: 编译命令末尾加
-s D:\Maven_Public\settings.xml。已下载的 jar 无需删除,Maven 只认本地有没有该 jar,不关心来源。
6.3 执行编译
cmd
cd /d D:\yudao-code\yudao-cloud
mvn clean install package -Dmaven.test.skip=true -s D:\Maven_Public\settings.xml
注意事项:
- cmd 中
-Dmaven.test.skip=true不加引号 ,加了会报Unknown lifecycle phase ".test.skip=true"。 - 首次编译需下载几百个 jar,屏幕会疯狂滚
Downloading...,属正常现象,不要按Ctrl+C。 - 编译阶段不连接 MySQL / Redis / Nacos,纯本地操作。
- 耗时约 5~20 分钟(取决于网速),看到以下输出即成功:
css
[INFO] BUILD SUCCESS
[INFO] Total time: ...
7. 启动项目(java -jar,不用 IDEA)
7.1 确认 jar 文件路径
编译产物在各模块的 target 目录下。每个模块会生成多个 jar,只有 -server 结尾的是可执行 Spring Boot jar ,-api 结尾的是接口定义包,不能启动。
查找命令:
cmd
dir /s /b D:\yudao-code\yudao-cloud\yudao-gateway\*.jar | findstr target
dir /s /b D:\yudao-code\yudao-cloud\yudao-module-system\*.jar | findstr target
dir /s /b D:\yudao-code\yudao-cloud\yudao-module-infra\*.jar | findstr target
踩坑记录: 凭经验猜测路径为
yudao-module-system-biz,实际目录名为yudao-module-system-server,dir报"系统找不到指定的路径"。解决: 用
dir /s /b ... | findstr target递归搜索,以实际输出为准。
本项目实际路径:
| 服务 | jar 路径 | 端口 |
|---|---|---|
| gateway | yudao-gateway\target\yudao-gateway.jar |
48080 |
| system | yudao-module-system\yudao-module-system-server\target\yudao-module-system-server.jar |
48081 |
| infra | yudao-module-infra\yudao-module-infra-server\target\yudao-module-infra-server.jar |
48082 |
7.2 按顺序启动
前提:MySQL、Redis、Nacos 均已运行,且 Nacos 中已创建 dev 命名空间。
必须按 gateway → system → infra 的顺序启动 ,每个服务占用一个独立 cmd 窗口(Win+R → cmd → 回车),因为 java -jar 会持续占用窗口输出日志。
窗口 1 --- gateway:
cmd
cd /d D:\yudao-code\yudao-cloud
java -jar yudao-gateway\target\yudao-gateway.jar
等待日志出现 Started GatewayServerApplication in x.xxx seconds。
窗口 2 --- system:
cmd
cd /d D:\yudao-code\yudao-cloud
java -jar yudao-module-system\yudao-module-system-server\target\yudao-module-system-server.jar
等待日志出现 Started SystemServerApplication in x.xxx seconds。
窗口 3 --- infra:
cmd
cd /d D:\yudao-code\yudao-cloud
java -jar yudao-module-infra\yudao-module-infra-server\target\yudao-module-infra-server.jar
等待日志出现 Started InfraServerApplication in x.xxx seconds。
7.3 浏览器验证
| 访问地址 | 期望返回 | 含义 |
|---|---|---|
http://127.0.0.1:48080 |
{"code":404,...} |
网关正常(根路径无接口,404 是预期行为) |
http://127.0.0.1:48081/admin-api/system/ |
{"code":401,"msg":"账号未登录",...} |
system 正常(未登录,401 是预期行为) |
http://127.0.0.1:48082/admin-api/infra/ |
{"code":401,"msg":"账号未登录",...} |
infra 正常 |
注意:
master-jdk17分支(Spring Boot 3.2)的 404 返回为{"code":404,"msg":"No static resource .","data":null},与文档中{"code":404,"data":null,"msg":null}略有不同,属版本差异,不影响判断 ,看到code:404即为成功。
8. 关闭项目(jps + taskkill,不用 IDEA)
8.1 查看 Java 进程
打开一个新的 cmd 窗口:
cmd
jps -l
输出示例:
sql
39076 yudao-gateway\target\yudao-gateway.jar
33544 yudao-module-system\yudao-module-system-server\target\yudao-module-system-server.jar
46648 yudao-module-infra\yudao-module-infra-server\target\yudao-module-infra-server.jar
26664 D:\nacos-server-2.3.2\nacos\target\nacos-server.jar
36776 com.intellij.idea.Main
5704 jdk.jcmd/sun.tools.jps.Jps
左侧为 PID (每次不同,以实际为准)。只需关注三个 yudao-xxx.jar 的 PID,其余进程(Nacos、IDEA 等)不要关 。最后一行 Jps 是命令自身,忽略。
8.2 关闭指定服务
cmd
taskkill /PID 39076 /F
taskkill /PID 33544 /F
taskkill /PID 46648 /F
将 PID 替换为
jps -l中看到的真实值 。/F表示强制终止。
每行执行后应返回:
makefile
成功: 已终止 PID 为 39076 的进程。
8.3 确认关闭
cmd
jps -l
三个 yudao-xxx.jar 行全部消失,而 Nacos、IDEA 等仍在,即关闭成功。
9. IDEA 导入后端项目并启动
第 7、8 节是纯命令行方式。本节是 IDEA 方式,日常开发改代码时更方便。两种方式二选一即可,不要同时用(会抢端口)。
9.1 导入项目
- 打开 IDEA → File → Open → 选择
D:\yudao-code\yudao-cloud(有pom.xml的那层)→ OK - 等待 IDEA 索引完成(右下角进度条走完,微服务项目首次约 3~10 分钟)
- 确认 JDK:File → Project Structure → Project → SDK ,选择 17(Temurin-17)
9.2 依次启动三个服务
按 Ctrl + Shift + N 搜索类名,打开后点类名左侧的 绿色 ▶ → Run:
| 顺序 | 搜索类名 | 端口 | 启动成功标志 |
|---|---|---|---|
| 1 | GatewayServerApplication |
48080 | Started GatewayServerApplication in x.xxx seconds |
| 2 | SystemServerApplication |
48081 | Started SystemServerApplication in x.xxx seconds |
| 3 | InfraServerApplication |
48082 | Started InfraServerApplication in x.xxx seconds |
必须按顺序启动 ,等上一个出现
Started再启动下一个。
9.3 停止服务
在 IDEA 底部 Run 窗口 ,点红色 ■ 停止按钮。
踩坑记录: 之前用
java -jar启动的 gateway 还在后台跑着,没关掉就直接在 IDEA 里启动,报错:
phpPort 48080 was already in use.解决: 先用
netstat -ano | findstr 48080找到占用端口的 PID,taskkill /PID xxx /F杀掉,再在 IDEA 里重新启动。规律:同一个端口只能跑一个进程。 不管用
java -jar还是 IDEA,切换之前先把旧的关掉。
9.4 启动日志中的 WARN 说明(不用管)
| 日志 | 含义 | 要处理吗 |
|---|---|---|
[Nacos Config] config[dataId=gateway-server-local.yaml] is empty |
Nacos 里没有该服务的远程配置,自动使用本地配置文件 | ❌ 正常,不用管 |
10. 前端项目启动与登录验证
10.1 环境要求
- Node.js > 16.18.0(推荐 LTS 版本)
- pnpm > 8.6.0
检查:
cmd
node -v
npm -v
若未安装 Node.js,前往 nodejs.org/ 下载 LTS 版,安装后重新打开 cmd 验证。
10.2 克隆前端项目
cmd
cd /d D:\yudao-code
git clone https://gitee.com/yudaocode/yudao-ui-admin-vue3.git
10.3 安装依赖
cmd
npm config set registry https://registry.npmmirror.com
npm install -g pnpm
cd /d D:\yudao-code\yudao-ui-admin-vue3
pnpm install
踩坑记录:
pnpm install结束后报:
bash[ERR_PNPM_IGNORED_BUILDS] Ignored build scripts: @parcel/watcher, core-js-pure, es5-ext, esbuild Run "pnpm approve-builds" to pick which dependencies should be allowed to run scripts.这是 pnpm 9.x 的安全机制,默认禁止依赖包运行构建脚本,不是报错。
解决:
cmdpnpm approve-builds弹出交互列表后,按
a全选,按回车 确认。然后再执行一次pnpm install即可。
10.4 确认后端连接配置(无需修改)
项目自带 .env.local 文件,已默认指向本地后端:
ini
VITE_BASE_URL='http://localhost:48080'
验证(可选):
cmd
type D:\yudao-code\yudao-ui-admin-vue3\.env.local | findstr VITE_BASE_URL
看到 VITE_BASE_URL='http://localhost:48080' 即正确,不需要改任何配置。
10.5 启动前端
前提:后端三个服务(gateway、system、infra)已在运行。
cmd
cd /d D:\yudao-code\yudao-ui-admin-vue3
npm run dev
等待出现:
arduino
VITE v4.x.x ready in xxx ms
➜ Local: http://localhost:80/
浏览器打开 http://localhost:80(首次加载约需 1 分钟,不要以为卡死)。
10.6 登录验证
| 字段 | 值 |
|---|---|
| 租户 | 芋道源码 |
| 用户名 | admin |
| 密码 | admin123 |
本地开发环境验证码已关闭(
.env.local中VITE_APP_CAPTCHA_ENABLE=false),直接点登录。
进入管理后台首页,看到左侧菜单栏 = 前后端联通,登录成功 ✅
接第 10 节续写。第 11 节为前端启动与登录------若你之前已把它并入第 10 节或单独记过,可跳过 11,直接从 12 接;其余为本次新增内容。
11. 前端项目启动与登录验证
11.1 环境要求
- Node.js > 16.18.0(推荐 LTS),pnpm > 8.6.0。
cmd
node -v
npm -v
未装 Node.js 则去 nodejs.org/ 装 LTS,装完重开 cmd 再验证。
11.2 克隆
cmd
cd /d D:\yudao-code
git clone https://gitee.com/yudaocode/yudao-ui-admin-vue3.git
11.3 安装依赖
cmd
npm config set registry https://registry.npmmirror.com
npm install -g pnpm
cd /d D:\yudao-code\yudao-ui-admin-vue3
pnpm install
踩坑:
pnpm install末尾报[ERR_PNPM_IGNORED_BUILDS] Ignored build scripts: @parcel/watcher, core-js-pure, es5-ext, esbuild。这是 pnpm 9.x 安全机制,默认禁止依赖运行构建脚本,非报错。 解决:
cmdpnpm approve-builds交互列表里按
a全选 → 回车 → 再执行一次pnpm install。
11.4 后端连接配置(无需修改)
.env.local 已默认指向本地网关:
ini
VITE_BASE_URL='http://localhost:48080'
验证(可选):
cmd
type D:\yudao-code\yudao-ui-admin-vue3\.env.local | findstr VITE_BASE_URL
11.5 启动前端
前提:后端 gateway / system / infra 已在运行。
cmd
cd /d D:\yudao-code\yudao-ui-admin-vue3
npm run dev
等待 VITE ... ready 与 Local: http://localhost:80/。首次打开页面约需 1 分钟(Vite 懒加载),勿误判为卡死。
11.6 登录验证
| 字段 | 值 |
|---|---|
| 租户 | 芋道源码 |
| 用户名 | admin |
| 密码 | admin123 |
本地验证码已关闭(.env.local 中 VITE_APP_CAPTCHA_ENABLE=false),直接登录。进入后台首页 = 前后端联通。
前端关闭:在 npm run dev 窗口按 Ctrl + C。
一键启动本地微服务项目(芋道平台为例)
在微服务架构(如芋道平台)中,开发环境的搭建历来是团队效率的瓶颈------容器化虽然能提供一致的环境、做到热加载与断点调试,但需要付出"镜像臃肿配置复杂、文件系统性能下降、调试需手动 Attach、依赖变更需重构建"的代价。
而"本地环境下一键启动"方法,正是针对这些摩擦的极简主义解法:它用预设脚本(如 start-env.bat)幂等地拉起 Nacos、前端这类本地进程,后端则由 IDEA Compound 一键并行启动;JDK、Maven 沿用机器预装环境,数据库等以本地服务预先常驻,从而把日常每次启动 收敛为一次点击。
它牺牲了环境一致性,换来了极致的开发反馈速度,以及一次配置、长期零操作的使用成本。对于以"快速迭代、频繁调试"为主要工作流的团队,其优势远大于弊端;而对于需要严格环境复用的 CI/CD 场景,则应优先考虑容器化方案。
前置准备
确保已安装并准备好以下内容(路径按实际情况替换):
| 项目 | 说明 | 示例路径 |
|---|---|---|
| JDK 8 / 11 | 后端运行环境 | --- |
| IntelliJ IDEA | 后端开发工具 | --- |
| Node.js | 前端运行环境 | --- |
| Nacos 2.3.2 | 服务注册 / 配置中心 | D:\nacos-server-2.3.2\nacos\bin |
| 前端项目 | Vue3 管理端 | D:\yudao-code\yudao-ui-admin-vue3 |
| 后端项目 | 在 IDEA 中打开的多模块工程 | 如 yudao-server、yudao-gateway 等 |
步骤 1:编写启动脚本 yudao-start-env.bat
目的 :用一个 bat 幂等地拉起 Nacos 和前端------并发调用时只起一个 Nacos、一个前端窗口,并且等 Nacos 就绪后再放行,避免后端抢跑注册失败。
在任意位置(建议 D:\yudao-code\)新建 yudao-start-env.bat,写入:
bat
@echo off
setlocal
rem ============ 配置区(按实际修改) ============
set NACOS_URL=http://127.0.0.1:8848/nacos/
set NACOS_BIN=D:\nacos-server-2.3.2\nacos\bin
set FRONT_DIR=D:\yudao-code\yudao-ui-admin-vue3
set NACOS_LOCK=%TEMP%\yudao_nacos_start.lck
set FRONT_LOCK=%TEMP%\yudao_front_start.lck
rem ============ 1) 处理 Nacos ============
call :PROBE %NACOS_URL%
if %errorlevel%==0 ( echo [Nacos] 已就绪,跳过。 & goto FRONT )
rem 没就绪 -> 抢锁;mkdir 在并发下只有一个进程能成功
mkdir "%NACOS_LOCK%" 2>nul
if %errorlevel%==0 (
echo [Nacos] 抢到锁,正在启动...
start "Nacos Server" cmd /k "cd /d %NACOS_BIN% && startup.cmd -m standalone"
set NACOS_OWNER=1
) else (
echo [Nacos] 已有进程在启动,本进程只等待。
set NACOS_OWNER=0
)
rem 无论是否抢到锁,都轮询等 8848 就绪
set /a W=0
:NACOS_WAIT
timeout /t 2 /nobreak >nul
call :PROBE %NACOS_URL%
if %errorlevel%==0 goto NACOS_OK
set /a W+=2
if %W% GEQ 120 (
echo [Nacos] 等待超时!请检查 Nacos 窗口;若锁残留请执行:rmdir /q "%NACOS_LOCK%"
goto FRONT
)
goto NACOS_WAIT
:NACOS_OK
echo [Nacos] 已就绪,再等 3 秒让 gRPC(9848) 稳定...
timeout /t 3 /nobreak >nul
if "%NACOS_OWNER%"=="1" rmdir "%NACOS_LOCK%" 2>nul
rem ============ 2) 处理 前端(进程探测,规避端口漂移) ============
:FRONT
tasklist /fi "IMAGENAME eq node.exe" 2>nul | find /i "node.exe" >nul
if %errorlevel%==0 ( echo [Front] 检测到 node 进程,认为前端已在运行,跳过。 & goto ENDBAT )
rem 没有 node 进程 -> 抢锁;mkdir 在并发下只有一个进程能成功
mkdir "%FRONT_LOCK%" 2>nul
if %errorlevel%==0 (
echo [Front] 抢到锁,正在启动...
start "Frontend Server" cmd /k "cd /d %FRONT_DIR% && npm run dev"
set FRONT_OWNER=1
) else (
echo [Front] 已有进程在启动,本进程只等待。
set FRONT_OWNER=0
)
rem 前端不被后端依赖,无需严格等就绪;轮询等 node 进程出现即可
set /a W=0
:FRONT_WAIT
timeout /t 2 /nobreak >nul
tasklist /fi "IMAGENAME eq node.exe" 2>nul | find /i "node.exe" >nul
if %errorlevel%==0 goto FRONT_OK
set /a W+=2
if %W% GEQ 60 (
echo [Front] 等待超时!请检查前端窗口/路径/npm;若锁残留请执行:rmdir /q "%FRONT_LOCK%"
goto ENDBAT
)
goto FRONT_WAIT
:FRONT_OK
echo [Front] node 进程已出现。
if "%FRONT_OWNER%"=="1" rmdir "%FRONT_LOCK%" 2>nul
:ENDBAT
exit /b 0
rem ============ 子过程:探测 URL 是否可连通(有响应即视为就绪) ============
:PROBE
curl -s -o nul -m 2 %~1 >nul 2>&1
exit /b %errorlevel%
- 用 pnpm 的把
npm run dev改成pnpm dev。 - 路径全部按实际改(集中在顶部"配置区")。
- 前端用探测
node.exe进程判断是否在运行,无需配置前端端口,Vite 端口漂移(80→81→82)不影响。 - Nacos 探测依赖
curl(Win10 1803+ 自带);若没有,把:PROBE里那行换成powershell -NoProfile -Command "try{$null=iwr '%~1' -UseBasicParsing -TimeoutSec 2;exit 0}catch{exit 1}"。
步骤 2:为每个后端模块创建 Application 配置
目的:让 IDEA 知道每个后端模块怎么启动。
- 打开 IDEA → 右上角运行配置下拉框 →
Edit Configurations...(编辑配置)。 - 左上角
+→ 选Application(应用程序)。 - 填写(以
yudao-server为例):- Name :
yudao-server - Main class :选该模块启动类(如
SystemServerApplication) - Module / classpath :选
yudao-module-system-server - 其余默认。
- Name :
Apply保存。- 重复 以上步骤,为所有要启动的后端模块各建一个 Application 配置(如
yudao-gateway、yudao-infra等)。
步骤 3:创建 Compound 复合配置(聚合后端)
目的:把上一步的所有后端配置"打包",点一次就能并行启动它们。
- 仍在
Edit Configurations...窗口 → 左上角+→ 选Compound(复合)。 - Name :
Start-All-Backends。 - 右侧 "Include these configurations / 包含的配置" 区域点
+,把步骤 2 建的全部后端 Application 配置勾上。 Apply保存。
步骤 4:把脚本注册为"外部工具"
目的:让 IDEA 认识这个 bat,后面才能在 Before launch 里引用它。
File → Settings(设置)→Tools(工具)→External Tools(外部工具)。- 点
+新建,填写:- Name :
yudao-start-env - Program(程序) :
D:\yudao-code\yudao-start-env.bat - Working directory(工作目录) :
D:\yudao-code - Arguments(参数):留空
- Name :
- 其余选项保持默认 ,点
OK。
步骤 5:把外部工具挂到"每一个"后端模块的 Before launch
目的 :借 Application 配置自带的 Before launch,在启动后端前先把 Nacos 和前端拉起来。Compound 是并行 启动各模块的,Before launch 只对"挂了它的模块"生效------所以要给每一个后端模块都挂上,让它们启动前都先等 Nacos 就绪;bat 自身幂等 + 互斥,挂多个模块也只会起一个 Nacos、一个前端窗口。
- 回到
Edit Configurations...,在左侧 应用程序 下,对每一个后端模块 (如yudao-gateway、yudao-server等)重复下面的 2~4 步。 - 点击
修改选项,勾选添加启动前任务,点+→ 选Run External Tool(运行外部工具)。(保留默认的构建) - 在弹出列表里选中步骤 4 建的
yudao-start-env→OK。 Apply保存。

步骤 6:一键启动
- IDEA 右上角运行配置下拉框选中
Start-All-Backends。 - 点绿色运行箭头 ▶。
实际发生的顺序:
sql
点 ▶ 运行 Compound
└─ IDEA 并行发起所有后端模块的启动
└─ 其中"被挂 Before launch 的那个模块"启动前
└─ 执行外部工具 Start-Env
└─ 运行 start-env.bat
├─ 新窗口:Nacos(standalone)
└─ 新窗口:前端 npm run dev
└─ bat 立即 exit 返回(不阻塞)
└─ 各后端模块继续编译、启动
最终你会看到:Nacos 窗口、前端窗口、以及 IDEA 里多个后端模块的日志同时在跑。✅ 真正的一键。
备选方案:更简单的"两步法"
如果你不想折腾 Before launch 的时序问题,下面这种其实更稳,很多人就这么用:
- 把 更加简单的
start-env.bat放桌面 / 固定到任务栏,开发前双击一下 → Nacos + 前端起来(常驻,不用每次重起)。 - 回 IDEA 选
Start-All-Backends点 ▶ → 后端起来。
优点:Nacos / 前端不随 IDEA 重启而反复重启,更省资源、更少报错;缺点:是"两下点击"而非"一下"。两种方案效果等价。
12. 阅读现有功能(后台页面)
目标不是"学会用每个按钮",而是建立结构认知:知道系统分几块、模块间关系、去哪找东西。
12.1 看任意页面的四步
| 看哪里 | 得到什么 |
|---|---|
| 左侧菜单 | 系统骨架(一共几大块) |
| 页面顶部绿条 | 该页的官方文档链接(可点击,优先读它) |
| 表格表头列名 | 该页数据的字段 |
| 右侧操作按钮 | 对该数据能做的动作 |
12.2 左侧菜单的两层结构
scss
地基(公共,所有项目都用)
├── 系统管理 用户/角色/菜单/部门/租户/字典
└── 基础设施 代码生成/文件/配置/定时任务/日志
业务(按需启用)
支付/商城/CRM/ERP/工作流(BPM)/报表/公众号/AI/会员
12.3 两个核心业务概念
- 多租户(SaaS):一套系统租给多家公司,数据隔离。顶部"请选择租户"= 进入哪家公司;租户列表 = 公司;租户套餐 = 档次(决定该租户能用哪些菜单)。
- RBAC 权限三角:用户 --- 角色 --- 权限。权限分两种:菜单权限(功能权限,能点哪些按钮)、数据权限(能看哪些数据)。在"角色管理"操作列的"菜单权限""数据权限"处配置。
12.4 开发者视角三问
每看一页,反推后端结构:
| 问 | 反推 |
|---|---|
| 这页管的"东西"是什么 | 后端有一张表 |
| 它和别的东西什么关系 | 表之间的外键关联 |
| 能对它做什么操作 | 后端有一组增删改查接口 |
12.5 建议动手(本地数据可随便造)
- 用户管理 → 新增,填一个用户并选部门、角色。
- 角色管理 → 某角色 → 菜单权限,观察弹出的菜单勾选树(即功能权限的形态)。
- 点 2~3 个绿条链接读文档。
要把"页面"和"代码"连起来,用第 13 节的 F12 定位法。
13. 拆解一条业务链路(页面 → 数据库)
以"用户管理"为例。所有模块结构相同,看懂一个即会看全部。
13.1 用 F12 抓到接口地址
- 浏览器进用户管理页,按 F12 → Network。
- 刷新页面或点搜索。
- 找名字带
user的请求(如page),看其 URL,形如http://localhost/admin-api/system/user/page?...。
13.2 由 URL 定位 Controller
在 IDEA 全局搜 URL 的后半段(如 user/page),跳到带 @GetMapping 的方法,即 UserController.getUserPage。类上的 @RequestMapping("/system/user") 即该控制器的"门牌"。
13.3 完整链路
sql
页面表格
↓ 请求 /system/user/page
UserController 接请求(总机)
↓ 调用
AdminUserService 接口(只声明,一行无 {})
↓ Ctrl+Alt+B 跳实现
AdminUserServiceImpl 实现(写逻辑,有 {})
↓ 调用
AdminUserMapper 查表
↓
AdminUserDO 表的倒影(一字段对应一列)
↓
数据库表 system_users
跳实现的快捷键: 光标在接口方法名上按
Ctrl + Alt + B(或点行号旁绿色下箭头)。Ctrl + 点击只会跳到接口声明(无方法体),需再跳一次才到实现类XxxServiceImpl。
13.4 类名后缀规律
| 后缀 | 层 | 作用 |
|---|---|---|
Controller |
接口层 | 接前端请求 |
Service |
业务层 | 接口声明 |
ServiceImpl |
业务层 | 逻辑实现 |
Mapper |
数据层 | 查表 |
DO |
实体 | 对应一张表 |
ReqVO |
入参 | 前端传来的参数/筛选条件 |
RespVO |
出参 | 返回前端的数据 |
Convert |
转换 | DO 与 VO 互转 |
13.5 权限注解
方法上的 @PreAuthorize("@ss.hasPermission('system:user:create')") 即权限校验,字符串 system:user:create 对应"角色管理 → 菜单权限"勾选树上的一个勾。未授权则接口拒绝、前端按钮不显示。
13.6 文件目录地图(system 模块)
sql
yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/
├── controller/admin/user/
│ ├── UserController.java
│ └── vo/ UserSaveReqVO / UserPageReqVO / UserRespVO
├── service/user/ AdminUserService / AdminUserServiceImpl
├── dal/dataobject/user/ AdminUserDO
├── dal/mysql/user/ AdminUserMapper
└── convert/ UserConvert
前端:
sql
yudao-ui-admin-vue3/src/
├── views/system/user/ index.vue(表格+按钮) / UserForm.vue(新增编辑弹窗)
└── api/system/user/ index.ts(接口地址清单)
14. 代码生成器
yudao 的核心提效手段:建表后自动生成增删改查全套代码与前端页面,只需补特殊业务逻辑。
14.1 入口
后台 → 基础设施 → 代码生成。
14.2 标准流程
sql
1. MySQL 建表(CREATE TABLE,定义字段、类型、注释)
2. 代码生成 → 导入该表 → 预览 → 下载
生成内容:DO / Mapper / Service / ServiceImpl / Controller /
ReqVO / RespVO / Convert / 前端 Vue 页面 / 菜单初始化 SQL
3. 将生成代码放入对应模块,前端页面放入 views 与 api 目录
4. 改特殊业务逻辑(生成的是通用骨架)
5. 系统管理 → 菜单管理 添加菜单与按钮权限,并给角色分配
6. 重启后端,测试
真正需要手写的只有第 4 步。第 13 节拆过的
UserController整套结构,生成器可一次产出。
15. 手动改一个字段练手(通知公告加 author)
在现有功能上改字段的最小闭环,用于体会"开发"动作。
15.1 改数据库
cmd
mysql -u root -p123456 ruoyi-vue-pro -e "ALTER TABLE system_notice ADD COLUMN author VARCHAR(50) DEFAULT '' COMMENT '作者';"
mysql -u root -p123456 ruoyi-vue-pro -e "DESC system_notice;"
15.2 改后端
NoticeDO加private String author;(字段名与列名自动映射,无需写 SQL)NoticeRespVO加private String author;NoticeSaveReqVO加private String author;
15.3 改前端
src/views/infra/notice/index.vue 表格列处加:
html
<el-table-column label="作者" prop="author" />
新增弹窗 NoticeForm.vue 如需录入,再加一个对应输入框。
15.4 生效
重启 system(前端 npm run dev 在跑则自动热更新)。通知公告页表格出现"作者"列即后端改动生效。复原方法见第 16、18 节。
16. 用 Git 分支隔离练习(安全网)
练习或做项目前开实验分支,主线(后端 master-jdk17、前端 master)永远不被污染。
16.1 开工清单
cmd
git status # 确认 clean;否则先 git restore .
git checkout -b experiment # 后端、前端各开一条
16.2 练习中撤销
cmd
git restore . # 撤销所有已修改文件
git clean -n # 预览将删除的未跟踪新文件
git clean -fd # 确认无误后真删(不可恢复,务必先 -n)
16.3 收工清单
cmd
git restore .
git checkout master-jdk17 # 后端主线(前端为 master)
git branch -D experiment
16.4 数据库复原(Git 管不到表)
- 撤一列:
mysql -u root -p123456 ruoyi-vue-pro -e "ALTER TABLE system_notice DROP COLUMN author;" - 整库恢复出厂:
DROP DATABASE+CREATE DATABASE+ 重导D:\yudao-code\yudao-cloud\sql\mysql\ruoyi-vue-pro.sql。
16.5 原理要点
- 分支是指针,非副本 :磁盘始终只有一份工作区文件;分支仅是
.git里指向某次提交的标签。切分支 = Git 把唯一工作区刷成该标签所指快照的内容。 - Git 改的是磁盘真实文件,IDEA 只是显示器 :IDEA 不持有代码,只读磁盘并被动刷新。验证:用记事本打开同一
.java,内容与 IDEA 一致;切分支后文件"修改日期"会更新。 .git隐藏文件夹 = 仓库数据库 ,住在项目根目录,存所有快照与分支指针。勿删,删后代码仍在但丢失全部历史与回退能力。- Git 靠"从当前目录向上查找
.git"定位仓库 ,找不到则报fatal: not a git repository。快照范围 =.git所在目录往下(除.gitignore忽略项)。
验证命令:
cmd
where git # git 程序位置(全局唯一)
dir /a D:\yudao-code\yudao-cloud\.git # 确认相册存在
git rev-parse --show-toplevel # 当前仓库根
cd /d D:\ && git status # 无 .git 处必报 not a git repository
17. 断点调试
调试只读不改文件,天然安全。用于读懂现有逻辑、验证改动。
17.1 打断点
在目标行行号左侧(gutter)单击,出现红点。再点取消。
17.2 必须用 Debug 模式启动
点类名旁虫子图标 启动(非绿三角、非 java -jar),否则断点不停。确认:IDEA 底部窗口标签为 Debug ,且含 Variables / Frames。
17.3 命中与查看
触发对应请求(刷新/搜索页面)→ IDEA 弹到最前、该行高亮并带绿箭头 = 命中。在 Variables 窗口展开对象(如 reqVO)查看真实入参值。
17.4 控制键
| 键 | 作用 |
|---|---|
| F8 | 执行当前行,停到下一行 |
| F7 | 跳进当前行调用的方法内部 |
| F9 | 继续运行到下一个断点或结束 |
17.5 查看真实 SQL
F8 执行 selectPage 等查询后,切 Debug 窗口的 Console,查看:
vbnet
==> Preparing: SELECT ... WHERE ... username LIKE ? ...
==> Parameters: %admin%(String)
<== Total: 1
比 F7 跳进框架代码更实用,排查"查不出数据"主要靠它。
18. 排查 Nacos 服务列表为空 / Unable to find instance
18.1 Nacos 的两项职责
| 职责 | 可否为空 | 为空后果 |
|---|---|---|
| 配置中心 | 可空(走本地 application-local.yaml) |
仅 WARN,无影响 |
| 注册中心(服务发现) | 不可空 | 网关报 Unable to find instance for xxx |
18.2 读懂报错措辞
Unable to find instance for xxx= 网关已连上 Nacos 并查了登记册,但册中无该服务 → 该服务进程未起或未注册。- 若为连接类报错(连不上 8848)才是 Nacos 本身未启动/地址错。
18.3 探针直测进程(绕开网关与 Nacos)
| 地址 | 进程存活应返回 | 否则 |
|---|---|---|
http://127.0.0.1:48080 |
{"code":404,...} |
打不开/拒绝连接 |
http://127.0.0.1:48081/admin-api/system/ |
{"code":401,...} |
打不开/拒绝连接 |
http://127.0.0.1:48082/admin-api/infra/ |
{"code":401,...} |
打不开/拒绝连接 |
配合 jps -l 看进程是否存在。打不开 = 进程未活,按对应模式重启并等 Started XxxApplication,再等数秒注册。
18.4 进程活但控制台空:命名空间 ID 与名不一致
踩坑: 代码中
namespace写死为字符串dev(启动日志namespace=dev为证)。若创建命名空间时"命名空间名"填dev、但"命名空间 ID"用了自动生成的 UUID,则服务注册到"ID=dev"的隐式桶,而控制台"dev 标签"指向 UUID 桶 → 列表空(public 亦空)。文档要求 ID 与名都为dev。 验证:看启动日志Nacos client key init properties的namespace=值,及[REGISTER-SERVICE] ... register finished。 注意:此情况下服务间仍能互相发现、登录与断点均正常,控制台空仅为显示问题,不影响功能。
两种修法:
- 方法 A(推荐本地) :删除 UUID 命名空间 → 新建命名空间,ID 与名均手动填
dev(ID 栏勿留空)→ 刷新控制台,通常无需重启即可见服务。 - 方法 B(规范/生产,保留 UUID) :将三个 server 模块配置中的
spring.cloud.nacos.discovery.namespace与spring.cloud.nacos.config.namespace改为该 UUID,三个服务都改并重启 ,使日志namespace=变为 UUID。
方法 B 注意:
localprofile 下生效的是application-local.yaml,会覆盖application.yaml,须改application-local.yaml(或两文件都改);三个服务须一致,否则互相发现不了。
日常复用速查
启动
sql
后端(IDEA 与 java -jar 二选一,勿同时用)
IDEA:依次 Run/Debug GatewayServerApplication → SystemServerApplication → InfraServerApplication
命令行(3 个独立 cmd):
java -jar yudao-gateway\target\yudao-gateway.jar
java -jar yudao-module-system\yudao-module-system-server\target\yudao-module-system-server.jar
java -jar yudao-module-infra\yudao-module-infra-server\target\yudao-module-infra-server.jar
前端(1 个 cmd,前提后端已起):
cd /d D:\yudao-code\yudao-ui-admin-vue3 && npm run dev
验证
perl
http://127.0.0.1:48080 → 404
http://127.0.0.1:48081/admin-api/system/ → 401
http://127.0.0.1:48082/admin-api/infra/ → 401
http://localhost:80 → admin / admin123 登录进后台
关闭
arduino
前端:npm run dev 窗口 Ctrl+C
后端 IDEA:Run/Debug 窗口红 ■
后端命令行:jps -l → taskkill /PID xxx /F(仅关 3 个 yudao 进程)
改代码后
ini
mvn clean install package -Dmaven.test.skip=true -s D:\Maven_Public\settings.xml
端口被占
r
netstat -ano | findstr 48080 # 取 PID
taskkill /PID xxx /F
调试
arduino
行号左侧点红点 = 断点;虫子图标启动 = Debug 模式
F8 走一行 / F7 跳进 / F9 继续;Variables 看变量;Console 看 SQL
Git 安全网
css
开工:git status → git checkout -b experiment
撤销:git restore . ;新文件 git clean -n 后 git clean -fd
收工:git restore . → git checkout 主线(后端 master-jdk17 / 前端 master)→ git branch -D experiment
Nacos 列表空排查
css
探针 48080/48081/48082 + jps -l 判断进程是否存活
进程活但空 → 命名空间 ID 与名不一致 → 方法 A(重建 ID=dev)或方法 B(改配置 namespace 为 UUID)
| 场景 | 命令 |
|---|---|
| 改了代码,重新编译 | mvn clean install package -Dmaven.test.skip=true -s D:\Maven_Public\settings.xml |
| 没改代码,直接启动 | 跳过编译,直接 java -jar ...(按 gateway → system → infra 顺序) |
启动报 Address already in use |
上次服务没关干净,jps -l 找到残留 PID,taskkill /PID xxx /F 后重新启动 |
| 查看当前所有 Java 进程 | jps -l |
| 关闭指定服务 | taskkill /PID xxx /F |
附:本次实操疑问 / 报错速查
| 现象 | 原因 | 处理 |
|---|---|---|
redis-server 报 *:6379 bind ... |
msi 已注册服务自启,端口被占 | 无需手动启动;redis-cli ping 得 PONG 即正常 |
| Redis 命令「先找不到、后又能用」 | 安装前未装、安装后已加 PATH | 正常,重开 cmd 即可 |
| Nacos 打开无登录页、直接进控制台 | 未开鉴权,免登录放行 | 正常,不要开启鉴权 |
| 数据库名能否改 / 是否要建连接 | 配置写死 ruoyi-vue-pro;命令行无「连接」概念 |
库名不可改;每次 -u -p 即连,无需预建连接 |