目录导航一、前言从 localhost 到公网 IP 的距离二、项目技术栈与服务器配置三、第一步宝塔面板安装运行环境3.1 登录宝塔面板3.2 软件商店一键安装四大组件四、第二步数据库初始化4.1 创建数据库与导入 SQL4.2 【踩坑①】init.sql 导入报错五、第三步Spring Boot 后端部署5.1 修改配置文件 application.yaml5.2 改造启动类输出个人信息5.3 打包、上传、后台/前台启动5.4 【踩坑②】UnsupportedClassVersionError5.5 【踩坑③】Lombok 编译失败六、第四步Vue 前端部署6.1 登录页从深色科技风改为白色商务风6.2 注册即登录优化用户体验6.3 能耗大屏 Dashboard加分模块6.4 npm 构建与文件上传七、第五步Nginx 反向代理配置7.1 配置原理图文详解7.2 完整配置文件7.3 【踩坑④】405 Method Not Allowed7.4 【踩坑⑤】Nginx 配置保存后仍 404八、第六步阿里云安全组放行端口九、部署架构全景图十、四大考核模块演示指南十一、排错速查手册10 个高频问题十二、总结与感悟一、前言从 localhost 到公网 IP 的距离作为计算机专业的学生在本地写完课程设计后老师要求将项目部署到云服务器并现场演示。刚开始我以为不就是上传一个 jar 包嘛结果从下午一直折腾到凌晨两点——JDK 版本不兼容、Lombok 编译报错、Nginx 405/404、能耗图表没有数据……每一个问题都在告诉我本地开发环境和生产部署是两码事。现在回过头来看这些问题都有清晰的解决方案只是当时没有人把它系统地写出来。所以我把整个部署过程整理成这篇博客涵盖从服务器购买到项目上线、再到四个考核模块演示的完整步骤每一条命令都是我在实际操作中跑通的。本文以《赛克能源》能源管理系统为案例全程使用宝塔面板降低 Linux 操作门槛适合正在做 Spring Boot Vue 课程设计的同学参考。 阅读本文你将获得① 宝塔面板搭建 Java Web 环境的完整流程② 前后端分离项目的部署方案③ Nginx 反向代理的核心配置原理④ 5 个真实踩坑经历与 10 个高频问题的排查方法。二、项目技术栈与服务器配置本文案例为《赛克能源》能源管理系统以下为完整技术栈层级技术选型版本/规格/说明云服务器阿里云轻量应用服务器2核 vCPU / 4GB 内存 / 50G ESSD 云盘操作系统Alibaba Cloud Linux 3OpenAnolis Edition兼容 CentOS 8管理面板宝塔 Linux 面板 9.2.0可视化服务器管理软件商店一键装环境Web 服务器Nginx 1.24.0静态资源托管 反向代理解决跨域后端框架Spring Boot 2.7.6MyBatis-Plus ORM JWT 无状态鉴权数据库MySQL 8.0.46InnoDB 引擎utf8mb4 字符集缓存中间件Redis 6.2.20用于 Token 缓存提升鉴权效率前端框架Vue 2.6.14 ECharts 6.0SPA 单页应用 数据可视化三、第一步宝塔面板安装运行环境3.1 登录宝塔面板通过阿里云控制台远程连接ECS Workbench登录服务器后执行bt default命令会显示外网面板地址、用户名和密码外网面板地址: http://47.107.40.48:8888/xxxxxxxxusername: xxxxxxxxpassword: xxxxxxxx用浏览器打开外网面板地址输入用户名密码即可登录。⚠️ 如果 8888 端口无法打开说明阿里云安全组未放行该端口。请先跳到第八章完成安全组配置。3.2 软件商店一键安装四大组件登录宝塔后点击左侧「软件商店」搜索并一键安装以下四个软件软件版本安装说明Nginx1.24选极速安装默认配置即可MySQL8.0安装过程中设置 root 密码为 123456Redis7.x保持默认配置不需要设密码OpenJDK1.8.0或在软件商店搜索安装Java项目管理器插件安装完成后在宝塔面板首页确认四个服务都处于「运行中」状态。至此Java Web 运行环境搭建完毕。 MySQL root 密码设为 123456 是为了和 application.yaml 保持一致。如果设了其他密码后续配置文件要同步修改。四、第二步数据库初始化4.1 创建数据库与导入 SQL宝塔面板 → 数据库 → 添加数据库数据库名ems用户名root密码123456创建完成后点击右侧「导入」按钮选择本地的 init.sql 文件执行导入。4.2 踩坑①init.sql 导入报错【现象】导入末尾出现以下错误共 7 行ERROR 1231 (42000) at line 1690: Variable time_zone cant be set to the value of NULLERROR 1231 (42000) at line 1692: Variable sql_mode cant be set to the value of NULLERROR 1231 (42000) at line 1693: Variable foreign_key_checks cant be set to the value of NULL...共 7 行【原因】MySQL 8.0 不再支持 SET 变量 NULL 的语法。init.sql 文件末尾的这几行是导出工具mysqldump自动添加的清理语句用于恢复会话变量对实际数据没有任何影响。【解决】在 SSH 终端中执行以下命令使用 --force 参数强制导入mysql -uroot -p123456 --force ems /opt/ems/sql/init.sql导入完成后验证mysql -uroot -p123456 -e USE ems; SHOW TABLES;输出应显示 49 张表含 sys_user、sys_menu、ems_device_energy_statistics 等。 如果只看到末尾 7 行 SET 语句报错说明数据已经完整导入可以放心使用。五、第三步Spring Boot 后端部署5.1 修改配置文件 application.yaml修改 src/main/resources/application.yaml确保连接信息正确server:port: 8763 # 后端监听端口servlet:context-path: /home # 统一路径前缀spring:datasource:url: jdbc:mysql://localhost:3306/ems?useUnicodetruecharacterEncodingUTF-8serverTimezoneGMT%2B8username: rootpassword: 123456 # 与 MySQL root 密码一致driver-class-name: com.mysql.cj.jdbc.Driverredis:host: localhost # 同一台服务器上使用 localhostport: 6379 为什么 MySQL 和 Redis 地址都写 localhost因为和后端在同一台服务器上localhost 就是最快最安全的连接方式。只有当数据库在独立的云服务器上时才需要写远程 IP 地址。5.2 改造启动类输出个人信息修改 EmsApplication.java 的 main 方法添加启动日志用于模块二考核时现场演示SpringBootApplicationpublic class EmsApplication {public static void main(String[] args) {SpringApplication.run(EmsApplication.class, args);System.out.println(《能源系统》API 服务 成功上线);System.out.println(服务器 IP: 47.107.40.48 服务端口: 8763);System.out.println(班级2024计算机应用技术2班);System.out.println(姓名薛智远);System.out.println(学号20246030990);System.out.println(考核时间2026-06-08);}}5.3 打包、上传、启动① 本地打包Mavenmvn clean package -DskipTests② 将 target/ 目录下的 jar 文件通过宝塔面板「文件」功能上传至服务器 /opt/ems/backend/ 目录。③ 后台启动保持服务持续运行nohup java -jar /opt/ems/backend/ems-0.0.1-SNAPSHOT.jar /opt/ems/backend/app.log 21 ④ 前台启动模块二演示使用实时打印日志cd /opt/ems/backend java -jar ems-0.0.1-SNAPSHOT.jar前台启动时终端会实时打印 Spring Boot 启动过程和自定义信息。演示完毕后按 CtrlC 停止再执行步骤③恢复后台服务。 验证后端是否启动成功执行 curl http://localhost:8763/home/lzq返回 HTML 页面即为正常。5.4 踩坑②UnsupportedClassVersionError【现象】Exception in thread main java.lang.UnsupportedClassVersionError:com/lzpu/EmsApplication has been compiled by a more recent version of the Java Runtime(class file version 61.0), this version of the Java Runtime only recognizes class fileversions up to 52.0【原因】class 版本号对照表版本号对应 JDK52.0JDK 861.0JDK 17本地开发环境使用 JDK 17 编译编译出的字节码版本号为 61。服务器安装的是 JDK 8最高只能识别版本 52 的字节码因此无法运行。【解决】编译时通过 --release 8 参数指定目标版本javac --release 8 -encoding UTF-8 -cp classpath EmsApplication.java然后用 jar 命令将编译后的 .class 文件更新到 jar 包中jar uf ems-0.0.1-SNAPSHOT.jar BOOT-INF/classes/com/lzpu/EmsApplication.class5.5 踩坑③Lombok 编译失败【现象】Fatal error compiling:java.lang.ExceptionInInitializerError: com.sun.tools.javac.code.TypeTag :: UNKNOWN【原因】项目中使用了 Lombok 的 Data、Getter、Setter 等注解。编译时 Lombok 注解处理器需要介入生成 getter/setter 方法但旧版 Lombok1.18.24 及以下与 JDK 17 的编译器 API 存在兼容性问题导致注解处理阶段崩溃。【解决】方案一推荐升级 maven-compiler-plugin 到 3.11.0Lombok 版本升级到 1.18.34plugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-compiler-plugin/artifactIdversion3.11.0/versionconfigurationsource1.8/sourcetarget1.8/targetannotationProcessorPathspathgroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.18.34/version/path/annotationProcessorPaths/configuration/plugin方案二快速方案对于不使用 Lombok 注解的类如 EmsApplication.java可以单独编译然后替换 jar 中的 class 文件绕过 Maven 编译流程。六、第四步Vue 前端部署6.1 登录页从深色科技风改为白色商务风原项目登录页为暗色科幻风格不符合企业管理系统定位。重构为白色简洁商务风· 整体布局1000×600px 白色卡片式两栏布局左侧 500px 照片区右侧 500px 表单区· 配色方案蓝色 #1677FF 作为主色调按钮、激活态白色 #FFFFFF 背景深灰 #333333 标题· 卡片样式圆角 16px柔和外阴影 box-shadow: 0 4px 20px rgba(0,0,0,0.08)· 左侧照片使用 object-fit: cover 填充整个区域无拉伸变形· 底部信息三行灰色文字分别显示学号、姓名、班级、考核日期· 响应式手机端自动切换为上下布局左侧图片缩小为 220px 高度6.2 注册即登录优化用户体验原项目注册成功后只切换到登录页并预填用户名用户仍需手动输入密码登录。优化后注册成功即自动登录// 注册成功后自动登录this.loginForm.username this.registerForm.username;this.loginForm.password this.registerForm.password;this.mode login;this.$nextTick(() this.onLogin()); // 等待 Vue DOM 更新后再执行登录这样可以有效避免用户因注册后还看到登录页而产生困惑提升演示时的流畅度。6.3 能耗大屏 Dashboard加分模块新增 EnergyDashboard 组件作为用户登录后的默认首页。使用 ECharts 6.0 实现能源管理仪表盘· 4 个统计卡片当月总能耗元、分组数量、组均能耗元、最高单组能耗元· 柱状图各分组能耗对比支持工具提示查看具体数值· 饼图各分组能耗占比环形样式带图例· 明细表分组名称、能耗费用、占比进度条一目了然· 月份切换可切换不同月份查看历史数据适配数据时间范围 2024-09 至 2026-01三个页面大屏、周度、月度之间通过顶部标签栏自由切换同时支持登出按钮返回登录页。6.4 npm 构建与文件上传npm installnpm run build构建完成后在宝塔面板操作网站 → 添加站点 → 域名填公网IP → PHP版本选纯静态。将 dist/ 目录下所有文件index.html、css/、js/、img/、favicon.ico上传至网站根目录如 /www/wwwroot/ems/。七、第五步Nginx 反向代理配置这是整个部署过程中最关键、也最容易出错的一步。理解原理比抄配置更重要。7.1 配置原理前后端分离的项目中前端页面由 Nginx80 端口直接返回但 API 请求如 /api/home/user/login实际上需要访问 Spring Boot 后端8763 端口。如果在浏览器中直接跨端口调用会因为浏览器的同源策略被拦截。Nginx 反向代理的作用在 80 端口上拦截所有以 /api/ 开头的请求将其转发到 8763 端口并把 /api/ 前缀去掉请求流程浏览器 → Nginx(:80) location /api/ → proxy_pass http://localhost:8763//api/home/user/login → 去掉 /api → /home/user/login → 转发到后端7.2 完整配置文件宝塔面板 → 网站 → 点击域名 → 配置文件将自动生成的内容替换为以下配置server {listen 80;server_name 47.107.40.48; # 替换为你的公网 IProot /www/wwwroot/ems; # 前端 dist 文件实际路径index index.html;charset utf-8;# ── 规则①默认请求 → 返回前端页面 ──# 对 Vue/Hash 路由try_files 确保刷新不 404location / {try_files $uri $uri/ /index.html;}# ── 规则②/api/ 前缀 → 转发后端 ──# ⚠️ proxy_pass 末尾的 / 极其重要# 有斜杠 去掉 /api 前缀后再转发# 无斜杠 原样转发会多出 /api 前缀导致 404location /api/ {proxy_pass http://localhost:8763/;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}# ── 规则③静态资源缓存 30 天 ──location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {expires 30d;add_header Cache-Control public, immutable;}}保存后执行sudo nginx -t # 检查语法sudo systemctl reload nginx # 重载配置 proxy_pass http://localhost:8763/ 末尾的 / 决定了路径处理。有 / 去掉 /api 前缀 → /home/user/login无 / 原样保留 → /api/home/user/login。我们的后端路径没有 /api 前缀所以必须有 /。7.3 踩坑④405 Method Not Allowed【现象】登录时前端控制台报 405 Method Not Allowed。前端发出的是 POST 请求但响应状态码为 405。【排查过程】第一步确认后端接口注解。查看 LoginController.java登录方法注解为 PostMapping(/login)确实只接受 POST。这一步排除后端注解问题。第二步直接 curl 测试后端绕过 Nginxcurl -s -X POST http://localhost:8763/home/user/login \-H Content-Type: application/json \-d {username:admin,password:123456}→ 有返回 token 字符串说明后端运行正常。第三步通过 Nginx 代理测试curl -s -X POST http://localhost/api/home/user/login \-H Content-Type: application/json \-d {username:admin,password:123456}→ 返回 404 或空响应说明 Nginx 转发环节有问题。第四步检查 Nginx 配置中的 proxy_pass 行发现末尾缺少 /。【根因】proxy_pass 末尾缺少 /导致请求被原样转发为 /api/home/user/login而 Spring Boot 没有 /api 前缀的路径返回 404。浏览器端由于 Nginx 的错误响应可能没有正确传递显示为 405。【解决】补上 proxy_pass 末尾的 /重载 Nginx。7.4 踩坑⑤Nginx 配置保存后仍 404【现象】在宝塔面板中修改配置文件并保存后nginx -t 检查通过但浏览器中所有 API 请求仍然返回 404。【排查】检查 /etc/nginx/conf.d/ 目录发现有多个 .conf 文件。宝塔创建网站时自动生成了一份默认配置文件修改后可能产生了备份文件。另一个 server 块默认配置抢先匹配了请求。【解决】删除多余配置文件只保留一个 ems.confls /etc/nginx/conf.d/ # 查看所有配置文件sudo rm /etc/nginx/conf.d/xxx.conf # 删除多余的sudo systemctl reload nginx # 重载八、第六步阿里云安全组放行端口阿里云控制台 → 轻量应用服务器 → 点击实例 → 防火墙 → 添加规则端口协议用途说明80TCP网站 HTTP 访问443TCPHTTPS 备用8763TCP后端 API 调试直接访问8888TCP宝塔面板入口⚠️ 安全组和系统防火墙是两层独立规则都需要配置。但阿里云轻量服务器一般默认关闭系统防火墙firewalld重点配置安全组即可。九、部署架构全景图经过以上六个步骤项目的完整部署架构如下Internet (公网)│▼┌──────────────────┐│ 阿里云安全组 │ ← 已放行 80/443/8763/8888└────────┬─────────┘│┌────────▼─────────┐│ Nginx (:80) │ 宝塔面板管理│ ││ / → dist/ 前端静态文件│ /api/* → proxy_pass → localhost:8763/└────────┬─────────┘│┌────────▼─────────┐│ Spring Boot │ :8763 (nohup 后台守护进程)│ context:/home ││ JWT Token 鉴权 │└──┬──────────┬────┘┌───────▼──┐ ┌─────▼─────┐│ MySQL 8.0 │ │ Redis 6.2 ││ :3306 │ │ :6379 │└───────────┘ └───────────┘所有服务运行在同一台服务器上内部通信均使用 localhost十、四大考核模块演示指南以下演示顺序是实践中验证的最佳流程确保现场顺畅不卡壳顺序模块名称分值具体操作展示内容①API 服务模块30分终端执行cd /opt/ems/backendjava -jar ems.jarSpring Boot 实时启动日志IP:47.107.40.48 端口:8763班级/姓名/学号/考核时间②首页模块30分浏览器打开http://47.107.40.48登录页照片个人信息登录 admin/123456注册后自动登录③大屏展示加分 10分登录后自动进入大屏 Dashboard4张统计卡片柱状图饼图分组明细表④能耗统计30分切换月份到 2025-12切换周度视图月度/周度数据图表正常显示数值 演示顺序说明先②登录首页给评委看 → 再①终端演示 API 服务 → 然后③展示大屏 → 最后④切月份看能耗数据。这个顺序逻辑连贯一气呵成。十一、排错速查手册10 个高频问题1. 405 Method Not Allowed请求方法不匹配。后端 PostMapping 只接受 POST浏览器地址栏发的是 GET。快速验证curl -X POST http://IP:8763/home/user/login -H Content-Type: application/json -d {username:admin,password:123456}2. Connection refused端口拒绝连接三步排查法① ps aux | grep java 确认 java 进程在运行 ② sudo netstat -tlnp | grep 8763 确认端口在监听 ③ 阿里云安全组确认已放行 8763 端口3. UnsupportedClassVersionErrorclass 版本不兼容本地 JDK 17 编译的字节码版本号 61无法在服务器 JDK 8版本号 52上运行。解决方案编译时加 --release 8 参数。4. Lombok 编译失败ExceptionInInitializerErrorJDK 17 旧版 Lombok 不兼容。方案一升级 maven-compiler-plugin → 3.11.0 Lombok → 1.18.34。方案二单独编译不依赖 Lombok 的类文件用 jar 命令更新。5. Nginx 转发后 404三个检查点① curl http://localhost:8763/home 确认后端正常 ② nginx -t 检查语法 ③ proxy_pass http://localhost:8763/ 末尾是否有 /决定是否去掉 /api 前缀6. 能耗图表没有数据数据时间范围为 2024-09 至 2026-01前端默认查询当前月份2026-06该月无数据。手动切换到 2025-12 即可看到完整图表数据。7. MySQL init.sql 导入报错Variable cant be set to NULLMySQL 8.0 不兼容 mysqldump 生成的结尾清理语句。执行 mysql --force ems init.sql 强制跳过即可不影响数据完整性。8. yum 安装 Nginx 被过滤阿里云镜像 /etc/yum.conf 中配置了 excludenginx。解决添加 Nginx 官方源 --disableexcludesall 参数安装。9. 宝塔面板网址打不开确认阿里云安全组已放行 8888 端口。SSH 连接服务器执行 bt default 确认当前面板地址和端口。测试curl -v http://localhost:8888。10. Nginx 配置修改后不生效修改配置文件后必须重载sudo systemctl reload nginx 或 nginx -s reload。如果还是没生效sudo systemctl restart nginx 强制重启。十二、总结与感悟从下午折腾到凌晨两点从一脸茫然到逐步理清思路——这次云部署经历让我深刻体会到1. 本地开发 ≠ 生产部署。本地能跑通的项目放到生产环境可能因为 JDK 版本、数据库版本、操作系统差异而出现各种意想不到的问题。环境一致性是 DevOps 的核心课题。2. 宝塔面板不是偷懒工具。它把繁琐的 yum 安装、配置文件编辑、服务管理变成了可视化操作让初学者把精力集中在理解架构原理上而不是和命令行较劲。3. Nginx 反向代理是前后端分离的桥梁。理解了 proxy_pass 末尾 / 的含义就理解了 Nginx 路径转发的核心逻辑。工程实践中 80% 的问题源于对细节的忽视。4. 排查问题的思路比记住答案更重要。遇到报错 → 缩小范围绕过 Nginx 直接测后端→ 逐层定位端口 → 进程 → 配置这套方法论适用于任何技术栈的排错。5. 文档即财富。踩过的每一个坑如果只是搞定了下次还会踩。把排查过程记录下来不仅帮别人更是帮未来的自己。
阿里云轻量服务器 + 宝塔面板:手把手教你将 Spring Boot + Vue 项目部署上线(附完整排错指南)
目录导航一、前言从 localhost 到公网 IP 的距离二、项目技术栈与服务器配置三、第一步宝塔面板安装运行环境3.1 登录宝塔面板3.2 软件商店一键安装四大组件四、第二步数据库初始化4.1 创建数据库与导入 SQL4.2 【踩坑①】init.sql 导入报错五、第三步Spring Boot 后端部署5.1 修改配置文件 application.yaml5.2 改造启动类输出个人信息5.3 打包、上传、后台/前台启动5.4 【踩坑②】UnsupportedClassVersionError5.5 【踩坑③】Lombok 编译失败六、第四步Vue 前端部署6.1 登录页从深色科技风改为白色商务风6.2 注册即登录优化用户体验6.3 能耗大屏 Dashboard加分模块6.4 npm 构建与文件上传七、第五步Nginx 反向代理配置7.1 配置原理图文详解7.2 完整配置文件7.3 【踩坑④】405 Method Not Allowed7.4 【踩坑⑤】Nginx 配置保存后仍 404八、第六步阿里云安全组放行端口九、部署架构全景图十、四大考核模块演示指南十一、排错速查手册10 个高频问题十二、总结与感悟一、前言从 localhost 到公网 IP 的距离作为计算机专业的学生在本地写完课程设计后老师要求将项目部署到云服务器并现场演示。刚开始我以为不就是上传一个 jar 包嘛结果从下午一直折腾到凌晨两点——JDK 版本不兼容、Lombok 编译报错、Nginx 405/404、能耗图表没有数据……每一个问题都在告诉我本地开发环境和生产部署是两码事。现在回过头来看这些问题都有清晰的解决方案只是当时没有人把它系统地写出来。所以我把整个部署过程整理成这篇博客涵盖从服务器购买到项目上线、再到四个考核模块演示的完整步骤每一条命令都是我在实际操作中跑通的。本文以《赛克能源》能源管理系统为案例全程使用宝塔面板降低 Linux 操作门槛适合正在做 Spring Boot Vue 课程设计的同学参考。 阅读本文你将获得① 宝塔面板搭建 Java Web 环境的完整流程② 前后端分离项目的部署方案③ Nginx 反向代理的核心配置原理④ 5 个真实踩坑经历与 10 个高频问题的排查方法。二、项目技术栈与服务器配置本文案例为《赛克能源》能源管理系统以下为完整技术栈层级技术选型版本/规格/说明云服务器阿里云轻量应用服务器2核 vCPU / 4GB 内存 / 50G ESSD 云盘操作系统Alibaba Cloud Linux 3OpenAnolis Edition兼容 CentOS 8管理面板宝塔 Linux 面板 9.2.0可视化服务器管理软件商店一键装环境Web 服务器Nginx 1.24.0静态资源托管 反向代理解决跨域后端框架Spring Boot 2.7.6MyBatis-Plus ORM JWT 无状态鉴权数据库MySQL 8.0.46InnoDB 引擎utf8mb4 字符集缓存中间件Redis 6.2.20用于 Token 缓存提升鉴权效率前端框架Vue 2.6.14 ECharts 6.0SPA 单页应用 数据可视化三、第一步宝塔面板安装运行环境3.1 登录宝塔面板通过阿里云控制台远程连接ECS Workbench登录服务器后执行bt default命令会显示外网面板地址、用户名和密码外网面板地址: http://47.107.40.48:8888/xxxxxxxxusername: xxxxxxxxpassword: xxxxxxxx用浏览器打开外网面板地址输入用户名密码即可登录。⚠️ 如果 8888 端口无法打开说明阿里云安全组未放行该端口。请先跳到第八章完成安全组配置。3.2 软件商店一键安装四大组件登录宝塔后点击左侧「软件商店」搜索并一键安装以下四个软件软件版本安装说明Nginx1.24选极速安装默认配置即可MySQL8.0安装过程中设置 root 密码为 123456Redis7.x保持默认配置不需要设密码OpenJDK1.8.0或在软件商店搜索安装Java项目管理器插件安装完成后在宝塔面板首页确认四个服务都处于「运行中」状态。至此Java Web 运行环境搭建完毕。 MySQL root 密码设为 123456 是为了和 application.yaml 保持一致。如果设了其他密码后续配置文件要同步修改。四、第二步数据库初始化4.1 创建数据库与导入 SQL宝塔面板 → 数据库 → 添加数据库数据库名ems用户名root密码123456创建完成后点击右侧「导入」按钮选择本地的 init.sql 文件执行导入。4.2 踩坑①init.sql 导入报错【现象】导入末尾出现以下错误共 7 行ERROR 1231 (42000) at line 1690: Variable time_zone cant be set to the value of NULLERROR 1231 (42000) at line 1692: Variable sql_mode cant be set to the value of NULLERROR 1231 (42000) at line 1693: Variable foreign_key_checks cant be set to the value of NULL...共 7 行【原因】MySQL 8.0 不再支持 SET 变量 NULL 的语法。init.sql 文件末尾的这几行是导出工具mysqldump自动添加的清理语句用于恢复会话变量对实际数据没有任何影响。【解决】在 SSH 终端中执行以下命令使用 --force 参数强制导入mysql -uroot -p123456 --force ems /opt/ems/sql/init.sql导入完成后验证mysql -uroot -p123456 -e USE ems; SHOW TABLES;输出应显示 49 张表含 sys_user、sys_menu、ems_device_energy_statistics 等。 如果只看到末尾 7 行 SET 语句报错说明数据已经完整导入可以放心使用。五、第三步Spring Boot 后端部署5.1 修改配置文件 application.yaml修改 src/main/resources/application.yaml确保连接信息正确server:port: 8763 # 后端监听端口servlet:context-path: /home # 统一路径前缀spring:datasource:url: jdbc:mysql://localhost:3306/ems?useUnicodetruecharacterEncodingUTF-8serverTimezoneGMT%2B8username: rootpassword: 123456 # 与 MySQL root 密码一致driver-class-name: com.mysql.cj.jdbc.Driverredis:host: localhost # 同一台服务器上使用 localhostport: 6379 为什么 MySQL 和 Redis 地址都写 localhost因为和后端在同一台服务器上localhost 就是最快最安全的连接方式。只有当数据库在独立的云服务器上时才需要写远程 IP 地址。5.2 改造启动类输出个人信息修改 EmsApplication.java 的 main 方法添加启动日志用于模块二考核时现场演示SpringBootApplicationpublic class EmsApplication {public static void main(String[] args) {SpringApplication.run(EmsApplication.class, args);System.out.println(《能源系统》API 服务 成功上线);System.out.println(服务器 IP: 47.107.40.48 服务端口: 8763);System.out.println(班级2024计算机应用技术2班);System.out.println(姓名薛智远);System.out.println(学号20246030990);System.out.println(考核时间2026-06-08);}}5.3 打包、上传、启动① 本地打包Mavenmvn clean package -DskipTests② 将 target/ 目录下的 jar 文件通过宝塔面板「文件」功能上传至服务器 /opt/ems/backend/ 目录。③ 后台启动保持服务持续运行nohup java -jar /opt/ems/backend/ems-0.0.1-SNAPSHOT.jar /opt/ems/backend/app.log 21 ④ 前台启动模块二演示使用实时打印日志cd /opt/ems/backend java -jar ems-0.0.1-SNAPSHOT.jar前台启动时终端会实时打印 Spring Boot 启动过程和自定义信息。演示完毕后按 CtrlC 停止再执行步骤③恢复后台服务。 验证后端是否启动成功执行 curl http://localhost:8763/home/lzq返回 HTML 页面即为正常。5.4 踩坑②UnsupportedClassVersionError【现象】Exception in thread main java.lang.UnsupportedClassVersionError:com/lzpu/EmsApplication has been compiled by a more recent version of the Java Runtime(class file version 61.0), this version of the Java Runtime only recognizes class fileversions up to 52.0【原因】class 版本号对照表版本号对应 JDK52.0JDK 861.0JDK 17本地开发环境使用 JDK 17 编译编译出的字节码版本号为 61。服务器安装的是 JDK 8最高只能识别版本 52 的字节码因此无法运行。【解决】编译时通过 --release 8 参数指定目标版本javac --release 8 -encoding UTF-8 -cp classpath EmsApplication.java然后用 jar 命令将编译后的 .class 文件更新到 jar 包中jar uf ems-0.0.1-SNAPSHOT.jar BOOT-INF/classes/com/lzpu/EmsApplication.class5.5 踩坑③Lombok 编译失败【现象】Fatal error compiling:java.lang.ExceptionInInitializerError: com.sun.tools.javac.code.TypeTag :: UNKNOWN【原因】项目中使用了 Lombok 的 Data、Getter、Setter 等注解。编译时 Lombok 注解处理器需要介入生成 getter/setter 方法但旧版 Lombok1.18.24 及以下与 JDK 17 的编译器 API 存在兼容性问题导致注解处理阶段崩溃。【解决】方案一推荐升级 maven-compiler-plugin 到 3.11.0Lombok 版本升级到 1.18.34plugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-compiler-plugin/artifactIdversion3.11.0/versionconfigurationsource1.8/sourcetarget1.8/targetannotationProcessorPathspathgroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.18.34/version/path/annotationProcessorPaths/configuration/plugin方案二快速方案对于不使用 Lombok 注解的类如 EmsApplication.java可以单独编译然后替换 jar 中的 class 文件绕过 Maven 编译流程。六、第四步Vue 前端部署6.1 登录页从深色科技风改为白色商务风原项目登录页为暗色科幻风格不符合企业管理系统定位。重构为白色简洁商务风· 整体布局1000×600px 白色卡片式两栏布局左侧 500px 照片区右侧 500px 表单区· 配色方案蓝色 #1677FF 作为主色调按钮、激活态白色 #FFFFFF 背景深灰 #333333 标题· 卡片样式圆角 16px柔和外阴影 box-shadow: 0 4px 20px rgba(0,0,0,0.08)· 左侧照片使用 object-fit: cover 填充整个区域无拉伸变形· 底部信息三行灰色文字分别显示学号、姓名、班级、考核日期· 响应式手机端自动切换为上下布局左侧图片缩小为 220px 高度6.2 注册即登录优化用户体验原项目注册成功后只切换到登录页并预填用户名用户仍需手动输入密码登录。优化后注册成功即自动登录// 注册成功后自动登录this.loginForm.username this.registerForm.username;this.loginForm.password this.registerForm.password;this.mode login;this.$nextTick(() this.onLogin()); // 等待 Vue DOM 更新后再执行登录这样可以有效避免用户因注册后还看到登录页而产生困惑提升演示时的流畅度。6.3 能耗大屏 Dashboard加分模块新增 EnergyDashboard 组件作为用户登录后的默认首页。使用 ECharts 6.0 实现能源管理仪表盘· 4 个统计卡片当月总能耗元、分组数量、组均能耗元、最高单组能耗元· 柱状图各分组能耗对比支持工具提示查看具体数值· 饼图各分组能耗占比环形样式带图例· 明细表分组名称、能耗费用、占比进度条一目了然· 月份切换可切换不同月份查看历史数据适配数据时间范围 2024-09 至 2026-01三个页面大屏、周度、月度之间通过顶部标签栏自由切换同时支持登出按钮返回登录页。6.4 npm 构建与文件上传npm installnpm run build构建完成后在宝塔面板操作网站 → 添加站点 → 域名填公网IP → PHP版本选纯静态。将 dist/ 目录下所有文件index.html、css/、js/、img/、favicon.ico上传至网站根目录如 /www/wwwroot/ems/。七、第五步Nginx 反向代理配置这是整个部署过程中最关键、也最容易出错的一步。理解原理比抄配置更重要。7.1 配置原理前后端分离的项目中前端页面由 Nginx80 端口直接返回但 API 请求如 /api/home/user/login实际上需要访问 Spring Boot 后端8763 端口。如果在浏览器中直接跨端口调用会因为浏览器的同源策略被拦截。Nginx 反向代理的作用在 80 端口上拦截所有以 /api/ 开头的请求将其转发到 8763 端口并把 /api/ 前缀去掉请求流程浏览器 → Nginx(:80) location /api/ → proxy_pass http://localhost:8763//api/home/user/login → 去掉 /api → /home/user/login → 转发到后端7.2 完整配置文件宝塔面板 → 网站 → 点击域名 → 配置文件将自动生成的内容替换为以下配置server {listen 80;server_name 47.107.40.48; # 替换为你的公网 IProot /www/wwwroot/ems; # 前端 dist 文件实际路径index index.html;charset utf-8;# ── 规则①默认请求 → 返回前端页面 ──# 对 Vue/Hash 路由try_files 确保刷新不 404location / {try_files $uri $uri/ /index.html;}# ── 规则②/api/ 前缀 → 转发后端 ──# ⚠️ proxy_pass 末尾的 / 极其重要# 有斜杠 去掉 /api 前缀后再转发# 无斜杠 原样转发会多出 /api 前缀导致 404location /api/ {proxy_pass http://localhost:8763/;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}# ── 规则③静态资源缓存 30 天 ──location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {expires 30d;add_header Cache-Control public, immutable;}}保存后执行sudo nginx -t # 检查语法sudo systemctl reload nginx # 重载配置 proxy_pass http://localhost:8763/ 末尾的 / 决定了路径处理。有 / 去掉 /api 前缀 → /home/user/login无 / 原样保留 → /api/home/user/login。我们的后端路径没有 /api 前缀所以必须有 /。7.3 踩坑④405 Method Not Allowed【现象】登录时前端控制台报 405 Method Not Allowed。前端发出的是 POST 请求但响应状态码为 405。【排查过程】第一步确认后端接口注解。查看 LoginController.java登录方法注解为 PostMapping(/login)确实只接受 POST。这一步排除后端注解问题。第二步直接 curl 测试后端绕过 Nginxcurl -s -X POST http://localhost:8763/home/user/login \-H Content-Type: application/json \-d {username:admin,password:123456}→ 有返回 token 字符串说明后端运行正常。第三步通过 Nginx 代理测试curl -s -X POST http://localhost/api/home/user/login \-H Content-Type: application/json \-d {username:admin,password:123456}→ 返回 404 或空响应说明 Nginx 转发环节有问题。第四步检查 Nginx 配置中的 proxy_pass 行发现末尾缺少 /。【根因】proxy_pass 末尾缺少 /导致请求被原样转发为 /api/home/user/login而 Spring Boot 没有 /api 前缀的路径返回 404。浏览器端由于 Nginx 的错误响应可能没有正确传递显示为 405。【解决】补上 proxy_pass 末尾的 /重载 Nginx。7.4 踩坑⑤Nginx 配置保存后仍 404【现象】在宝塔面板中修改配置文件并保存后nginx -t 检查通过但浏览器中所有 API 请求仍然返回 404。【排查】检查 /etc/nginx/conf.d/ 目录发现有多个 .conf 文件。宝塔创建网站时自动生成了一份默认配置文件修改后可能产生了备份文件。另一个 server 块默认配置抢先匹配了请求。【解决】删除多余配置文件只保留一个 ems.confls /etc/nginx/conf.d/ # 查看所有配置文件sudo rm /etc/nginx/conf.d/xxx.conf # 删除多余的sudo systemctl reload nginx # 重载八、第六步阿里云安全组放行端口阿里云控制台 → 轻量应用服务器 → 点击实例 → 防火墙 → 添加规则端口协议用途说明80TCP网站 HTTP 访问443TCPHTTPS 备用8763TCP后端 API 调试直接访问8888TCP宝塔面板入口⚠️ 安全组和系统防火墙是两层独立规则都需要配置。但阿里云轻量服务器一般默认关闭系统防火墙firewalld重点配置安全组即可。九、部署架构全景图经过以上六个步骤项目的完整部署架构如下Internet (公网)│▼┌──────────────────┐│ 阿里云安全组 │ ← 已放行 80/443/8763/8888└────────┬─────────┘│┌────────▼─────────┐│ Nginx (:80) │ 宝塔面板管理│ ││ / → dist/ 前端静态文件│ /api/* → proxy_pass → localhost:8763/└────────┬─────────┘│┌────────▼─────────┐│ Spring Boot │ :8763 (nohup 后台守护进程)│ context:/home ││ JWT Token 鉴权 │└──┬──────────┬────┘┌───────▼──┐ ┌─────▼─────┐│ MySQL 8.0 │ │ Redis 6.2 ││ :3306 │ │ :6379 │└───────────┘ └───────────┘所有服务运行在同一台服务器上内部通信均使用 localhost十、四大考核模块演示指南以下演示顺序是实践中验证的最佳流程确保现场顺畅不卡壳顺序模块名称分值具体操作展示内容①API 服务模块30分终端执行cd /opt/ems/backendjava -jar ems.jarSpring Boot 实时启动日志IP:47.107.40.48 端口:8763班级/姓名/学号/考核时间②首页模块30分浏览器打开http://47.107.40.48登录页照片个人信息登录 admin/123456注册后自动登录③大屏展示加分 10分登录后自动进入大屏 Dashboard4张统计卡片柱状图饼图分组明细表④能耗统计30分切换月份到 2025-12切换周度视图月度/周度数据图表正常显示数值 演示顺序说明先②登录首页给评委看 → 再①终端演示 API 服务 → 然后③展示大屏 → 最后④切月份看能耗数据。这个顺序逻辑连贯一气呵成。十一、排错速查手册10 个高频问题1. 405 Method Not Allowed请求方法不匹配。后端 PostMapping 只接受 POST浏览器地址栏发的是 GET。快速验证curl -X POST http://IP:8763/home/user/login -H Content-Type: application/json -d {username:admin,password:123456}2. Connection refused端口拒绝连接三步排查法① ps aux | grep java 确认 java 进程在运行 ② sudo netstat -tlnp | grep 8763 确认端口在监听 ③ 阿里云安全组确认已放行 8763 端口3. UnsupportedClassVersionErrorclass 版本不兼容本地 JDK 17 编译的字节码版本号 61无法在服务器 JDK 8版本号 52上运行。解决方案编译时加 --release 8 参数。4. Lombok 编译失败ExceptionInInitializerErrorJDK 17 旧版 Lombok 不兼容。方案一升级 maven-compiler-plugin → 3.11.0 Lombok → 1.18.34。方案二单独编译不依赖 Lombok 的类文件用 jar 命令更新。5. Nginx 转发后 404三个检查点① curl http://localhost:8763/home 确认后端正常 ② nginx -t 检查语法 ③ proxy_pass http://localhost:8763/ 末尾是否有 /决定是否去掉 /api 前缀6. 能耗图表没有数据数据时间范围为 2024-09 至 2026-01前端默认查询当前月份2026-06该月无数据。手动切换到 2025-12 即可看到完整图表数据。7. MySQL init.sql 导入报错Variable cant be set to NULLMySQL 8.0 不兼容 mysqldump 生成的结尾清理语句。执行 mysql --force ems init.sql 强制跳过即可不影响数据完整性。8. yum 安装 Nginx 被过滤阿里云镜像 /etc/yum.conf 中配置了 excludenginx。解决添加 Nginx 官方源 --disableexcludesall 参数安装。9. 宝塔面板网址打不开确认阿里云安全组已放行 8888 端口。SSH 连接服务器执行 bt default 确认当前面板地址和端口。测试curl -v http://localhost:8888。10. Nginx 配置修改后不生效修改配置文件后必须重载sudo systemctl reload nginx 或 nginx -s reload。如果还是没生效sudo systemctl restart nginx 强制重启。十二、总结与感悟从下午折腾到凌晨两点从一脸茫然到逐步理清思路——这次云部署经历让我深刻体会到1. 本地开发 ≠ 生产部署。本地能跑通的项目放到生产环境可能因为 JDK 版本、数据库版本、操作系统差异而出现各种意想不到的问题。环境一致性是 DevOps 的核心课题。2. 宝塔面板不是偷懒工具。它把繁琐的 yum 安装、配置文件编辑、服务管理变成了可视化操作让初学者把精力集中在理解架构原理上而不是和命令行较劲。3. Nginx 反向代理是前后端分离的桥梁。理解了 proxy_pass 末尾 / 的含义就理解了 Nginx 路径转发的核心逻辑。工程实践中 80% 的问题源于对细节的忽视。4. 排查问题的思路比记住答案更重要。遇到报错 → 缩小范围绕过 Nginx 直接测后端→ 逐层定位端口 → 进程 → 配置这套方法论适用于任何技术栈的排错。5. 文档即财富。踩过的每一个坑如果只是搞定了下次还会踩。把排查过程记录下来不仅帮别人更是帮未来的自己。