12 KiB
QH-MES 部署与热部署方案
本文档记录 QH-MES(jeecg-boot 3.9.2)在 Windows Server 上的部署方案,包含后端、前端的一键发版流程、关键配置、踩过的坑,以及未来上线客户正式服务器的规划。 最后更新:2026-06-17
一、环境概况
测试服务器(当前)
- 系统:Windows Server 2016 Standard
- JDK:17.0.11(
C:\Program Files\Java\jdk-17,注意JAVA_HOME要指根目录,不能带\bin) - Maven:3.9.8(
D:\apache-maven-3.9.8,从本地 Win11 拷过去的,因服务器网络受限无法在线下载) - Git:已装在
C:\Program Files\Git,但不在 PATH(用完整路径"C:\Program Files\Git\cmd\git.exe"调用) - Gitea:跑在同一台机器,裸仓库在
D:\gitea\data\gitea-repositories\chenx\qhmes.git,Web 地址http://27.223.88.102:33000/chenx/qhmes - Nginx:1.30.1,装在
D:\qhmes\nginx-1.30.1\,前端文件目录D:\qhmes\nginx-1.30.1\html\jeecg\ - Node/pnpm/npm:服务器上没装(前端不在服务器构建)
关键路径
| 用途 | 路径 |
|---|---|
| 后端运行目录(jar + WinSW 服务) | D:\qhmes\ |
| 后端运行 jar | D:\qhmes\jeecg-system-start-3.9.2.jar |
| 服务器源码工作副本 | D:\qhmes-src\(从本地裸仓库 clone,分支 main) |
| 前端 nginx 目录 | D:\qhmes\nginx-1.30.1\html\jeecg\ |
| WinSW 服务程序/配置 | D:\qhmes\qhmes-service.exe / qhmes-service.xml |
| 后端发版脚本 | D:\deploy-server.bat(放源码目录外,避免 git pull 自我覆盖) |
本地开发机(Win11)
- 项目路径:
D:\XSL-PROJECT\QH-MES\qhmes - 后端模块:
jeecg-boot/,前端:jeecgboot-vue3/(同一个 git 仓库) - 传文件到服务器的方式:向日葵远程传输(只能手动,不能脚本化)
二、后端部署(已跑通 ✅)
2.1 后端做成 Windows 服务(WinSW)
后端不再手动 java -jar(关窗口/断 RDP 就掉),改用 WinSW 注册成 Windows 服务,开机自启、崩溃自动重启。
- 服务 id:
qhmes,名称:QH-MES Backend - 配置文件
D:\qhmes\qhmes-service.xml关键内容:<executable>java</executable> <arguments>-Xms1g -Xmx2g -jar "D:\qhmes\jeecg-system-start-3.9.2.jar"</arguments> <workingdirectory>D:\qhmes</workingdirectory> <logpath>D:\qhmes\logs</logpath> <onfailure action="restart" delay="10 sec"/> - 注意:
<arguments>里不加--spring.profiles.active,因为 profile 已在打包时烤进 jar(见第四节)。 - 常用命令(管理员):
D:\qhmes\qhmes-service.exe install # 安装服务(一次性) D:\qhmes\qhmes-service.exe start # 启动 D:\qhmes\qhmes-service.exe stop # 停止 - 查日志:
启动成功标志:
Get-Content D:\qhmes\logs\qhmes-service.out.log -Wait -Tail 60Started JeecgSystemApplication in xx seconds,Tomcat 监听 8888。
2.2 一键发版脚本 D:\deploy-server.bat
流程:git pull → mvn 打包(prod) → 停服务 → 换 jar → 启服务。脚本自带 git pull,双击即自动拉最新代码。
@echo off
setlocal
set SRC=D:\qhmes-src
set GIT="C:\Program Files\Git\cmd\git.exe"
set DEPLOY_DIR=D:\qhmes
set JAR_NAME=jeecg-system-start-3.9.2.jar
set SVC=D:\qhmes\qhmes-service.exe
set BUILT_JAR=%SRC%\jeecg-boot\jeecg-module-system\jeecg-system-start\target\%JAR_NAME%
echo [1/5] git pull ...
cd /d %SRC%
%GIT% pull
if errorlevel 1 ( echo [ERROR] git pull failed & pause & exit /b 1 )
echo [2/5] maven package with prod profile ...
cd /d %SRC%\jeecg-boot
call mvn clean package -pl jeecg-module-system/jeecg-system-start -am -DskipTests -P prod -T 1C
if errorlevel 1 ( echo [ERROR] build failed & pause & exit /b 1 )
if not exist "%BUILT_JAR%" ( echo [ERROR] built jar not found & pause & exit /b 1 )
echo [3/5] stop service ...
"%SVC%" stop
timeout /t 6 /nobreak >nul
echo [4/5] copy new jar ...
copy /Y "%BUILT_JAR%" "%DEPLOY_DIR%\%JAR_NAME%"
if errorlevel 1 ( echo [ERROR] copy failed, jar locked? & pause & exit /b 1 )
echo [5/5] start service ...
"%SVC%" start
echo ===== DEPLOY DONE =====
endlocal
pause
2.3 后端发版流程
- 本地改代码 →
git push(推到main) - RDP/向日葵到服务器 → 双击
D:\deploy-server.bat - 看日志确认
Started ... in xx seconds
首次构建会下载几百 MB 依赖(约 8 分钟),缓存在
D:\maven-repo,之后每次只需 1~3 分钟。
三、前端部署(脚本已就绪)
前端 jeecgboot-vue3 用 pnpm 构建,产物 dist/,放到 nginx 的 html\jeecg\。
因服务器没 Node 且网络受限,前端不在服务器构建,而是:本地构建 → dist 走 git → 服务器拉取替换。
jeecgboot-vue3/dist被.gitignore忽略,所以构建后复制到根目录web-dist文件夹(未被忽略)再提交。
3.1 本地构建脚本 build-frontend.bat(本地 Win11 双击)
核心构建步骤与官网一致:pnpm install + pnpm run build,之后自动复制 dist 到 web-dist 并 git push。
@echo off
setlocal
set REPO=%~dp0
set WEBDIST=%REPO%web-dist
echo [1/4] build frontend (pnpm install + build) ...
cd /d %REPO%jeecgboot-vue3
call pnpm install
if errorlevel 1 ( echo [ERROR] pnpm install failed & pause & exit /b 1 )
call pnpm run build
if errorlevel 1 ( echo [ERROR] frontend build failed & pause & exit /b 1 )
if not exist "%REPO%jeecgboot-vue3\dist\index.html" ( echo [ERROR] dist/index.html not found & pause & exit /b 1 )
echo [2/4] refresh web-dist folder ...
if exist "%WEBDIST%" rmdir /S /Q "%WEBDIST%"
mkdir "%WEBDIST%"
xcopy "%REPO%jeecgboot-vue3\dist\*" "%WEBDIST%\" /E /Y /I >nul
echo [3/4] git add and commit web-dist ...
cd /d %REPO%
git add web-dist
git commit -m "frontend build dist update"
echo [4/4] git push ...
git push
if errorlevel 1 ( echo [ERROR] git push failed & pause & exit /b 1 )
echo ===== FRONTEND BUILT AND PUSHED =====
endlocal
pause
3.2 服务器部署脚本 D:\deploy-frontend.bat(服务器双击)
@echo off
setlocal
set SRC=D:\qhmes-src
set GIT="C:\Program Files\Git\cmd\git.exe"
set WEB=D:\qhmes\nginx-1.30.1\html\jeecg
set NGINX_DIR=D:\qhmes\nginx-1.30.1
echo [1/3] git pull ...
cd /d %SRC%
%GIT% pull
if errorlevel 1 ( echo [ERROR] git pull failed & pause & exit /b 1 )
if not exist "%SRC%\web-dist\index.html" ( echo [ERROR] web-dist not found, run build-frontend.bat first & pause & exit /b 1 )
echo [2/3] replace nginx frontend files ...
if exist "%WEB%" rmdir /S /Q "%WEB%"
mkdir "%WEB%"
xcopy "%SRC%\web-dist\*" "%WEB%\" /E /Y /I >nul
if errorlevel 1 ( echo [ERROR] copy failed & pause & exit /b 1 )
echo [3/3] reload nginx (ignore error if not running) ...
cd /d %NGINX_DIR%
nginx.exe -s reload
echo ===== FRONTEND DEPLOY DONE =====
endlocal
pause
nginx 不用重启:静态文件替换后自动生效。
nginx -s reload是平滑重载,不要直接跑nginx.exe(会报端口占用)。
3.3 前端发版流程(两步双击)
- 本地双击
build-frontend.bat(构建 + 推送 web-dist) - 服务器双击
D:\deploy-frontend.bat(拉取 + 替换 + reload) - 刷新浏览器
四、配置(profile)说明 —— 重点
4.1 哪个配置生效,由打包时的 Maven -P 决定
application.yml 里 spring.profiles.active: '@profile.name@' 是 Maven 占位符,打包时填入:
| 打包命令 | 生效配置 |
|---|---|
mvn package(不带 -P) |
dev(默认,<activeByDefault> 在 dev 上) |
mvn package -P prod |
prod |
mvn package -P test |
test |
发版脚本用的是
-P prod,所以烤进 jar 的是 prod 配置,运行时无需再加--spring.profiles.active。
4.2 判断一个 jar 用的哪个配置
- 看启动日志:
The following 1 profile is active: "prod" - 解压 jar 看
BOOT-INF/classes/application.yml里active的实际值 - 运行时
--spring.profiles.active=xxx可强制覆盖
4.3 dev vs prod 的区别(本项目)
| 项 | dev | prod(当前测试服务器用) |
|---|---|---|
| 端口 | 8888 | 8888(已改成与现网一致) |
| MySQL | xsl.qdxsl.top:50768(公网绕一圈) |
127.0.0.1:3306(本机直连) |
| MySQL 密码 | 123456 | 123456(已改,原为 root) |
重要事实:
xsl.qdxsl.top:50768与本机127.0.0.1:3306是同一个生产库(公网域名+端口转发到本机)。prod 走本机直连更快更稳。 prod 配置的修改在application-prod.yml,已带update-begin/update-end痕迹注释。
五、踩过的坑(避免重复)
- bat 文件乱码/无法执行:bat 里写中文 + 存成 UTF-8,cmd 按 GBK 读会乱码,连
@echo off都坏。→ bat 只用英文 ASCII,不带 BOM。 - WinSW 报
Invalid character in encoding:xml 里中文存成了 ANSI/GBK。→ 用 UTF-8 保存,或描述改英文。 - 服务用 prod 启动报
Access denied for user 'root':prod 密码原写的root,实际应为123456。 - PowerShell 下载报
未能创建 SSL/TLS 安全通道:Server 2016 默认 TLS 1.0。→ 先[Net.ServicePointManager]::SecurityProtocol = ... -bor 3072开启 TLS 1.2。 - 服务器下载被
127.0.0.1:10080的本机 Apache 拦截 404:服务器网络有本机代理/DNS 劫持,外网下载不通。→ Maven/Node 等在本地下好,向日葵拷过去。 mvn报JAVA_HOME not defined correctly:JAVA_HOME误设成了...\jdk-17\bin。→ 应为根目录...\jdk-17。git clone D:\gitea\...qhmes.git拿到的没有源码:那是 Gitea 裸仓库(只有 git 底层数据)。→git clone它到D:\qhmes-src得到工作副本。- cmd 里
cd D:\xxx不切盘:要用cd /d D:\xxx;&是 PowerShell 语法,cmd 里不能用。 - PowerShell 粘贴 here-string 卡在
>>:终止符'@没识别。→ 大段内容改用记事本另存为(All Files + ANSI),或写进 git 拉取。
六、未来上线客户正式服务器的规划(待落地)
核心原则:测试服务器可以 git 拉源码+构建;客户正式服务器只部署"已构建的成品",不放源码、不装构建工具、不依赖我方 gitea。
6.1 目标流程
我方(测试服务器/开发机):打包出成品(jar + 前端dist)并测好
↓ 向日葵/U盘/网盘 传过去
客户正式服务器:双击 deploy.bat → 停服务 → 换jar → 换前端 → 启服务
6.2 必做改造:配置外置(同一 jar 走天下)
现在 prod 配置(数据库/IP/密码)烤死在 jar 里,是测试服务器的。客户的库不同,需把配置挪到 jar 外:
D:\qhmes\
├── jeecg-system-start-3.9.2.jar ← 所有环境通用,不用为每个客户重打
└── config\
└── application-prod.yml ← 本机专属:客户的数据库/IP/密码
Spring Boot 自动优先读 jar 同级 config\ 目录的配置(外部 > jar 内 classpath)。
6.3 待办(上线时找 Claude 做)
- 把 prod 配置从 jar 内挪到外部
config\,jar 变环境无关 - 写"打 release 包"脚本:一键产出
jar + 前端dist + deploy.bat发布包 - 写客户服务器
deploy.bat:只"换文件+重启",不构建、不拉源码 - (建议)测试服务器也提前切到外置配置,与客户环境保持一致,上线零改动
七、快速命令速查
# 后端发版
D:\deploy-server.bat # 服务器双击
# 前端发版
build-frontend.bat # 本地 Win11 双击
D:\deploy-frontend.bat # 服务器双击
# 看后端日志
Get-Content D:\qhmes\logs\qhmes-service.out.log -Wait -Tail 60
# 后端服务控制(管理员)
D:\qhmes\qhmes-service.exe stop|start|status
# nginx 平滑重载(在 nginx 目录下)
cd /d D:\qhmes\nginx-1.30.1
nginx.exe -s reload