若依代码生成自动部署脚本开发实践
·
若依代码生成自动部署脚本开发实践
本文记录了为若依框架开发代码生成自动部署脚本的完整过程,包括遇到的问题、解决方案和最佳实践。
背景
若依(RuoYi)框架提供了强大的代码生成功能,可以快速生成前后端 CRUD 代码。但每次生成后需要手动解压 ZIP 包,然后按照目录结构逐个复制文件到项目中,这个过程非常繁琐且容易出错。
目标:开发一个自动化脚本,实现一键部署生成的代码
需求分析
- 自动解压 ZIP 文件
- 智能识别目录结构(兼容不同版本的若依代码生成格式)
- 自动复制文件到正确的项目位置
- 友好提示部署进度和结果
- 支持拖拽操作,提升用户体验
使用方法
先下载压缩包,解压后修改deploy-core文件中的backendRoot和frontendRoot变量为自己的项目目录
方式一:拖拽运行(推荐)
- 双击
deploy.bat - 将 ZIP 文件拖拽到窗口
- 按回车键
- 等待自动完成
方式二:命令行参数
deploy.bat C:\path\to\article.zip
方式三:直接拖拽到 BAT 文件
直接将 ZIP 文件拖拽到 deploy.bat 图标上即可自动执行。
技术方案演进
方案一:纯 PowerShell 脚本(初版)
实现思路
使用 PowerShell 编写单个脚本文件,包含所有逻辑。
遇到的问题
问题 1:中文字符编码错误
# 错误示例 - 保存为 UTF-8 无 BOM 时
Write-Host "临时目录保留在: $tempDir"
# 报错信息
所在位置 C:\deploy.ps1:106 字符: 1
+ } catch {
+ ~
表达式或语句中包含意外的标记"}"。
原因分析:
- PowerShell 对文件编码敏感
- 中文字符在不同编码下会被错误解析
- Windows 记事本默认可能保存为 GBK 编码
解决方案:
- 使用英文避免编码问题
- 或使用 UTF-8 with BOM 编码保存
- 或在脚本开头强制设置编码
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
问题 2:拖拽功能不工作
# 这种方式在某些环境下不支持拖拽
$zipFile = Read-Host "请输入路径"
原因分析:
Read-Host在某些 PowerShell 版本中对拖拽支持不完善- 控制台输入处理方式导致
尝试的解决方案:
- 使用
[System.Console]::ReadLine()- 部分有效 - 从剪贴板读取路径 - 需要额外权限
- 使用命令行参数 - 最稳定但不友好
问题 3:目录结构识别不准确
初始脚本假设 ZIP 解压后的结构是:
ruoyi/
├── main/java
└── ruoyi-ui/src/api
但实际若依代码生成的结构是:
article/
├── main/java
├── vue/api
└── articleMenu.sql
解决方案:增加智能探测逻辑
# 检测多种可能的路径
$possiblePaths = @(
(Join-Path $sourceRoot "main/java"),
(Join-Path $sourceRoot "ruoyi/main/java"),
(Join-Path $sourceRoot "src/main/java")
)
foreach ($path in $possiblePaths) {
if (Test-Path $path) {
# 找到正确的路径
break
}
}
方案二:批处理 + PowerShell 双文件架构(最终方案)✅
经过多次尝试,最终采用双文件分离架构,完美解决了所有问题。
架构设计
deploy.bat ← 用户界面层(中文,支持拖拽)
↓ 调用
deploy-core.ps1 ← 核心逻辑层(英文,无编码问题)
文件 1:deploy.bat(入口文件)
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion
echo ========================================
echo 若依代码生成自动部署工具
echo ========================================
echo.
REM 获取 ZIP 文件路径(支持拖拽)
if "%~1"=="" (
echo 提示: 可以直接拖拽 ZIP 文件到窗口中
echo 或者手动输入完整路径
echo.
set /p ZIP_PATH="请输入 ZIP 文件路径: "
) else (
set ZIP_PATH=%~1
)
REM 清理路径中的引号
set ZIP_PATH=%ZIP_PATH:"=%
REM 验证文件
if not exist "%ZIP_PATH%" (
echo.
echo 错误: 文件不存在: %ZIP_PATH%
pause
exit /b 1
)
if /i not "%ZIP_PATH:~-4%"==".zip" (
echo.
echo 错误: 不是有效的 ZIP 文件
pause
exit /b 1
)
echo.
echo ZIP 文件: %ZIP_PATH%
echo.
REM 调用 PowerShell 核心脚本
powershell -ExecutionPolicy Bypass -File "%~dp0deploy-core.ps1" "%ZIP_PATH%"
echo.
pause
优势:
- ✅ 批处理原生支持拖拽
- ✅ 中文界面无编码问题
- ✅ 可以作为
.bat直接双击运行 - ✅ 支持命令行参数
%~1
文件 2:deploy-core.ps1(核心逻辑)
# RuoYi Auto Deploy Core Script
param(
[string]$ZipFile
)
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
# 配置路径
$backendRoot = "C:\Users\15154\Desktop\ruoyi\RuoYi-Vue-fast"
$frontendRoot = "C:\Users\15154\Desktop\ruoyi\RuoYi-Vue3"
# 验证输入
if (-not $ZipFile) {
Write-Host "Error: No ZIP file specified" -ForegroundColor Red
exit 1
}
$ZipFile = $ZipFile.Trim('"').Trim()
if (-not (Test-Path $ZipFile)) {
Write-Host "Error: File does not exist" -ForegroundColor Red
exit 1
}
# 创建临时目录
$tempDir = Join-Path $env:TEMP "ruoyi-deploy-$(Get-Date -Format 'yyyyMMddHHmmss')"
New-Item -ItemType Directory -Path $tempDir | Out-Null
try {
# 1. 解压
Write-Host "[1/6] Extracting..." -ForegroundColor Yellow
Expand-Archive -Path $ZipFile -DestinationPath $tempDir -Force
Write-Host " OK" -ForegroundColor Green
# 2. 检测目录结构
Write-Host "[2/6] Detecting structure..." -ForegroundColor Yellow
$sourceRoot = $tempDir
$subdirs = Get-ChildItem -Path $tempDir -Directory
if ($subdirs.Count -eq 1) {
$sourceRoot = $subdirs[0].FullName
}
# 3. 部署后端
Write-Host "[3/6] Deploying backend..." -ForegroundColor Yellow
$mainJavaPath = Join-Path $sourceRoot "main/java"
$mainResourcesPath = Join-Path $sourceRoot "main/resources"
if (Test-Path $mainJavaPath) {
Copy-Item -Path "$mainJavaPath/*" -Destination (Join-Path $backendRoot "src/main/java") -Recurse -Force
Write-Host " Java files copied" -ForegroundColor Green
}
if (Test-Path $mainResourcesPath) {
Copy-Item -Path "$mainResourcesPath/*" -Destination (Join-Path $backendRoot "src/main/resources") -Recurse -Force
Write-Host " Resources copied" -ForegroundColor Green
}
# 复制 SQL 文件
$sqlFiles = Get-ChildItem -Path $sourceRoot -Filter "*.sql" -File
if ($sqlFiles.Count -gt 0) {
foreach ($sqlFile in $sqlFiles) {
Copy-Item -Path $sqlFile.FullName -Destination (Join-Path $backendRoot "sql") -Force
Write-Host " SQL: $($sqlFile.Name)" -ForegroundColor Green
}
}
# 4. 部署前端
Write-Host "[4/6] Deploying frontend..." -ForegroundColor Yellow
$vueApiPath = Join-Path $sourceRoot "vue/api"
$vueViewsPath = Join-Path $sourceRoot "vue/views"
if (Test-Path $vueApiPath) {
Copy-Item -Path "$vueApiPath/*" -Destination (Join-Path $frontendRoot "src/api") -Recurse -Force
Write-Host " API files copied" -ForegroundColor Green
}
if (Test-Path $vueViewsPath) {
Copy-Item -Path "$vueViewsPath/*" -Destination (Join-Path $frontendRoot "src/views") -Recurse -Force
Write-Host " View files copied" -ForegroundColor Green
}
# 5. 清理
Write-Host "[5/6] Cleaning up..." -ForegroundColor Yellow
Remove-Item -Path $tempDir -Recurse -Force
Write-Host " OK" -ForegroundColor Green
# 6. 完成
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " Deployment Completed!" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Next steps:" -ForegroundColor Yellow
Write-Host " 1. Restart backend application" -ForegroundColor White
Write-Host " 2. Refresh frontend or run npm run dev" -ForegroundColor White
Write-Host " 3. Execute SQL in sql/ directory" -ForegroundColor White
Write-Host " 4. Assign menu permissions" -ForegroundColor White
Write-Host ""
} catch {
Write-Host ""
Write-Host "ERROR: $_" -ForegroundColor Red
Write-Host "Temp dir kept: $tempDir" -ForegroundColor Yellow
exit 1
}
优势:
- ✅ 纯英文无编码问题
- ✅ 通过
param()接收参数 - ✅ 完整的错误处理
- ✅ 详细的调试输出
核心技术要点
1. 智能目录结构探测
# 支持多种若依代码生成格式
$detectionRules = @{
"vue/api" = "新版本的若依代码生成"
"ruoyi-ui/src/api" = "旧版本的若依代码生成"
"main/java" = "标准后端结构"
"ruoyi/main/java" = "带前缀的后端结构"
}
foreach ($rule in $detectionRules.Keys) {
$testPath = Join-Path $sourceRoot $rule
if (Test-Path $testPath) {
Write-Host "Detected: $($detectionRules[$rule])"
# 使用这个路径
break
}
}
2. 安全的文件复制
# 复制前检查源路径是否存在
if (Test-Path $sourcePath) {
# 使用 -Force 覆盖已存在的文件
# 使用 -Recurse 递归复制子目录
Copy-Item -Path "$sourcePath/*" -Destination $destPath -Recurse -Force
# 列出复制的文件用于确认
$files = Get-ChildItem -Path $sourcePath -Recurse -File
Write-Host "Copied $($files.Count) files"
}
3. 临时文件管理
# 创建带时间戳的临时目录(避免冲突)
$tempDir = Join-Path $env:TEMP "ruoyi-deploy-$(Get-Date -Format 'yyyyMMddHHmmss')"
try {
# 执行部署逻辑
...
} catch {
# 出错时保留临时目录用于调试
Write-Host "Temp dir kept: $tempDir" -ForegroundColor Yellow
exit 1
} finally {
# 成功时清理临时文件
if ($success) {
Remove-Item -Path $tempDir -Recurse -Force
}
}
4. 友好的用户反馈
# 使用颜色区分不同类型的消息
Write-Host "[1/6] Processing..." -ForegroundColor Yellow # 进行中
Write-Host " ✓ Done" -ForegroundColor Green # 成功
Write-Host " ⚠ Warning" -ForegroundColor Yellow # 警告
Write-Host " ✗ Error" -ForegroundColor Red # 错误
Write-Host " Debug info" -ForegroundColor DarkGray # 调试信息
总结
学到的经验
-
编码问题是 PowerShell 脚本的最大陷阱
- 尽量避免在 PowerShell 中使用非 ASCII 字符
- 如果必须使用,确保文件编码为 UTF-8 with BOM
- 或者使用批处理作为外壳
-
拖拽功能的实现技巧
- 批处理(
.bat)原生支持拖拽(通过%~1) - PowerShell 的
Read-Host对拖拽支持不稳定 - 双文件架构可以兼顾两者优势
- 批处理(
-
目录结构探测的重要性
- 不要硬编码路径
- 使用多种规则匹配,提高兼容性
- 提供详细的调试输出
-
错误处理的最佳实践
- 使用
try-catch捕获异常 - 出错时保留临时文件用于调试
- 提供清晰的错误信息和解决建议
- 使用
更多推荐



所有评论(0)