前后端分离项目本地联调跑得欢一上服务器就各种幺蛾子——要么接口 502要么刷新页面 404要么前端白屏什么都打不开。这种经历我相信不少人都遇到过。网上讲宝塔面板部署的教程不少但多数只讲了“把文件传上去、点几下按钮”至于为什么这么配、跨域是怎么被解决的、502 到底是谁的问题基本没讲透。这篇文章我就按自己实际部署 SpringBoot Vue 前后端分离项目的流程把宝塔面板部署上线的完整链路拆开讲从架构规划、打包自检、Nginx 反向代理到 SSL 配置和故障排查尽量做到“照做就能成报错也能自己查”。先说清楚这套东西适合谁看项目用的是 SpringBoot 做后端接口、Vue 做前端页面部署目标是云服务器上的宝塔面板系统。你可能是自己练手项目的学生也可能是刚接手公司部署任务的新手运维。只要你手里有这样一个前后端分离项目并且准备用宝塔把线上环境跑起来这篇文章应该能省下你不少瞎折腾的时间。1. 动手之前先把部署架构想清楚三种文件放哪里、端口怎么规划很多人一上来就急着打包、上传结果后端没起、前端没配、Nginx 写成一锅粥。部署前后端分离项目第一步不是敲命令而是把架构在脑子里理顺。我见过太多部署失败案例最后根因都是“没想清楚谁跟谁通信”。1.1 前后端分离部署的本质是“两个进程加一个入口”部署模型其实非常简单拆开看就三块前端Vue构建后是一堆静态文件HTML、JS、CSS、图片本身不需要运行环境只需要一个能托管静态文件的 Web 服务器。我们用的是 Nginx。后端SpringBoot一个可执行的 jar 包内部自带 Tomcat通过java -jar启动后监听某个端口提供接口服务。Nginx 的两重身份作为 Web 服务器托管前端静态文件同时作为反向代理把接口请求转发给后端 jar。说得直白点浏览器打开你的域名Nginx 先把首页 HTML 和 JS 资源发给它浏览器执行 JS 后开始发 Ajax 请求请求路径是/api/xxxNginx 一看这个前缀就转发给127.0.0.1:8080的 SpringBoot 进程。整个过程浏览器只知道自己在访问你的域名压根不知道后端的存在。1.2 端口规划与放行清单前后端分离部署最容易忽略的就是端口。默认规划可以参考下面这张表具体项目按实际调整组件默认端口作用是否对外开放Nginx80 / 443托管前端、反向代理80 和 443 对外开放SpringBoot8080后端接口服务不对公网开放只允许本机访问MySQL3306数据库强烈建议只允许本机访问宝塔面板8888面板管理不同宝塔版本有差异仅限你管理时访问用完可关这里有个很多人踩过的坑云服务器厂商的安全组规则和宝塔面板的防火墙是两套独立的东西必须同时放行。你宝塔里放行了 80 端口但云服务商安全组没加规则外部照样访问不了。反过来也一样。所以部署第一步先把云服务商控制台的安全组 80/443 放行再在宝塔面板的“安全”菜单里放行对应端口。1.3 目录规划服务器上的目录建议一次性规划好不要东一个西一个。我用的是宝塔默认站点目录下的项目名分目录方式例如/www/wwwroot/你的项目名/ ├── dist/ # Vue 打包产物 ├── server/ # jar 包、启动脚本、日志文件 └── logs/ # 可选单独放 nginx 或后端日志目录规划的意义在于出现问题时你能快速定位文件位置写 Nginx 配置时 root 路径也不会写错。后面所有配置都基于这个目录结构展开你可以按自己的习惯微调但前后端分开放、别把 jar 直接扔在 dist 里这一点务必坚持。2. 前端 Vue 项目构建打包前的三个检查点前端打包看似一条npm run build命令解决但实际把 dist 丢到服务器上跑起来后最先出问题的往往就是前端。2.1 环境准备与依赖安装本地先确认 Node.js 版本和包管理器类型。Vue 3 Vite 项目通常要求 Node 14 以上低版本会直接构建报错。建议先用一个干净目录拉取项目代码再执行依赖安装# 查看当前 Node 版本尽量 16 node -v # 安装依赖尽量用 npm ci 锁定依赖版本避免 package-lock 变更 npm ci # 也可以使用 pnpm速度更快 pnpm install我个人习惯在部署前删掉本地node_modules重新安装一遍因为长期开发中依赖可能变得很脏重新安装能规避很多“本地行、别人不行”的灵异问题。另外构建机上打包和服务器上打包结果理论上一致但为了速度通常建议在自己电脑或专门的构建服务器上打包然后把 dist 上传到服务器。如果你是直接把代码 git clone 到服务器上用宝塔终端构建也不是不行但服务器内存小于 1GB 时打包很容易被 kill 掉这时候还是本地打包更省心。2.2 接口地址配置从 axios baseURL 到环境变量前端代码里请求接口时写的地址是整个部署的核心。开发环境下很多人用 Vite 代理解决跨域请求路径写的是相对路径/api/login代理规则把/api转发到http://localhost:8080。这种写法到了生产环境其实是最省事的——因为生产环境我们同样会用 Nginx 把/api转发到后端服务前端代码一行都不用改。但如果你的代码在开发时写死了http://localhost:8080这样的绝对地址上线前必须改成环境变量控制的方式。推荐在项目根目录创建.env.production文件Vite 项目或使用相应的环境变量机制# .env.production VITE_API_BASE_URL/api然后在封装 axios 的地方读取它const service axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL || /api, timeout: 15000 })这么做的好处是前端构建产物里所有请求都是同源的浏览器不会产生跨域问题后续接口都走 Nginx 转发后端也不需要为了部署环境单独开 CORS。这一点我后面讲跨域原理时会再展开。2.3 构建命令与 dist 产物自检执行构建命令前重点检查两处配置Vite 的base配置和路由 history 模式。如果是 Vite 项目默认base是/通常不需要改。但如果你把前端部署到某个子路径下比如https://域名/admin那base就要对应修改。多数全站部署的场景保持/即可。createWebHistory这种 history 路由模式在开发环境没问题但部署到 Nginx 后刷新页面容易 404需要配合 Nginx 的try_files配置后面 Nginx 部分会提到。构建命令按项目而定# Vite 项目 npm run build # Vue Cli 项目 npm run build:prod构建完成后检查 dist 目录正常应该生成index.html和一个带 hash 的 js/css 目录。这时候在本地用简单的静态服务器预览一下产物# 如果本机有 python3 cd dist python3 -m http.server 8081然后浏览器打开http://localhost:8081看页面是否正常渲染、接口请求路径是否是/api开头。这时候接口当然会报错因为本地没有后端但你至少能确认静态资源引用路径没毛病。如果预览时控制台一堆资源 404多半是base配错了先解决再上传。3. SpringBoot 后端打包、数据库准备与进程管理前端产物是静态文件扔上去就能访问后端则需要老老实实处理环境差异。后端部署的复杂度主要不在打包而在于配置文件区分、启动方式管理和数据库迁移。3.1 打包前必须检查的三类配置SpringBoot 项目通常有application.yml和多个 profile 文件。我强烈建议你至少准备一套生产环境专用的 profile也就是application-prod.yml。里面重点检查三类内容第一是数据库连接。本地一般连的是localhost服务器上要改成 MySQL 的实际地址和端口。如果 MySQL 和 jar 在同一台服务器可以写127.0.0.1:3306不要把数据库密码写在配置里并被 git 仓库公开生产环境建议用环境变量覆盖。配置可以这样写spring: datasource: url: jdbc:mysql://127.0.0.1:3306/your_db_name?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/Shanghai username: your_db_user password: your_db_password第二是服务端口。SpringBoot 默认 8080如果你改了端口务必记住后面 Nginx 的proxy_pass要和它保持一致。端口不要用 80因为 80 要给 Nginx 用。第三是文件上传和日志路径。如果项目里有上传功能上传目录在本地可能是相对路径部署后必须改成服务器上的绝对路径否则文件会写到启动目录下的随机位置重启后还可能丢。日志路径也要显式配置方便后面排查问题。3.2 Maven 打包与本地启动验证打包命令很简单但有几个参数值得注意# 跳过测试、指定生产 profile 执行打包 mvn clean package -DskipTests -P prod打包后在target目录下会生成 jar 文件比如demo-0.0.1-SNAPSHOT.jar。建议在本地先执行一次生产配置启动确认配置没写错java -jar target/demo-0.0.1-SNAPSHOT.jar --spring.profiles.activeprod本地如果能正常启动并连上数据库再传到服务器。如果本地都无法启动生产配置那问题出在配置本身别指望到了服务器上就能神奇变好。服务器上还需要确认 Java 环境。宝塔面板的软件商店里有 Java 项目管理器不同版本可能叫法不同但更通用的方式是自己安装 OpenJDK# CentOS / 宝塔常用系统环境示例 yum install -y java-11-openjdk java -version如果你的项目用了 Java 17 甚至 21 的特性记得安装对应版本版本不对启动时会直接报 UnsupportedClassVersionError一眼就能看出来。3.3 启动脚本别用裸 java -jar有经验的部署者都会写启动脚本而不是直接java -jar命令行跑。原因很简单你需要能暂停、能重启、能把日志落到文件里裸命令放到 SSH 终端里终端一关进程就没了。下面是一个简洁但实用的启动/停止脚本放在 server 目录下#!/bin/bash # start.sh APP_NAME你的jar包名.jar LOG_FILE/www/wwwroot/你的项目名/server/app.log nohup java -jar $APP_NAME \ --spring.profiles.activeprod \ --server.port8080 \ $LOG_FILE 21 echo PID: $! echo $! app.pid停止脚本#!/bin/bash # stop.sh if [ -f app.pid ]; then PID$(cat app.pid) kill -9 $PID 2/dev/null rm -f app.pid echo 应用已停止 else pkill -f 你的jar包名.jar echo 已按进程名停止 fi有了这两个脚本后续更新发布就是“停止、替换 jar、启动”三个动作十分钟搞定。启动后第一时间看日志tail -f /www/wwwroot/你的项目名/server/app.log看到类似Started DemoApplication in 5.32 seconds或者Tomcat started on port(s): 8080就说明后端已经起来了。3.4 数据库迁移与初始化如果你用的是 MySQL部署前一定要在宝塔面板里新建一个数据库并把本地的表结构和初始数据导入。这一步可以等到了宝塔面板软件准备环节一起做但逻辑上属于后端准备的一部分别等到 jar 启动后才想起数据库没建。导入方式很简单宝塔的 phpMyAdmin 里选择数据库再点击“导入”选择.sql文件即可。如果数据量较大用命令行导入更稳妥mysql -u用户名 -p密码 数据库名 本地导出的.sql文件注意编码问题导入前确认 SQL 文件本身是 UTF-8 编码导入后在 MySQL 里用show variables like character%看一下避免出现中文乱码。4. 宝塔面板侧准备Nginx、MySQL 与站点目录后端 jar 和前端 dist 都准备好了接下来才进入宝塔面板的正题。宝塔版本之间的界面略有差异但核心操作路径大致相同。4.1 软件商店安装 Nginx 与 MySQL打开宝塔面板左侧菜单进入“软件商店”在运行环境分类下安装 Nginx 和 MySQL。版本选择建议软件推荐版本理由Nginx1.22稳定官网长期维护的 mainline 版本即可MySQL5.7 或 8.0根据本地开发版本选5.7 和 8.0 的 SQL 兼容性差异要注意Pure-FTPd需要时安装用于文件传输宝塔文件管理器也能替代MySQL 安装时间比较长可以先去把其他操作做了。装完 MySQL 后记得在“数据库”菜单里新建一个数据库并创建一个专用账号账号权限只分配这个库不要直接给 root 远程权限。这是安全底线生产环境尤其重要。4.2 创建站点与绑定域名在宝塔“网站”菜单里点击“添加站点”填上你的域名比如www.example.comPHP 版本选择“纯静态”因为在前后端分离架构下Nginx 只需要托管静态文件不需要处理 PHP。数据库选项如果已经有库就选择不创建。站点创建完成后宝塔会自动生成一个站点根目录通常位于/www/wwwroot/你填写的域名/。这里我建议把前端 dist 内容直接上传到这个目录或者像我目录规划中那样在站点根目录下分开管理。等等这里要说清楚站点的根目录就是给 Nginx 用的 root 目录所以前端文件应该放在这里。后端 jar 可以放在站点根目录下的子目录 server 里也可以单独放/home/app/看你习惯。核心是 Nginx 的 root 指向必须是 dist 文件所在路径。4.3 上传文件宝塔文件管理器最省事上传 dist 和 jar我用得最多的是宝塔自带的文件管理器不需要额外配置 FTP 账号。把 dist 整个目录压缩成 zip 上传然后再在服务器上解压。这样做比一个个上传几百个小文件快得多。# 在站点根目录下解压 cd /www/wwwroot/你的项目名 unzip dist.zipjar 包也一样直接传到 server 目录。上传后别急着启动先改权限chmod x start.sh stop.sh chmod 755 你的jar包名.jar5. 跨域问题的本质与 Nginx 反向代理配置这是全文最核心的部分。很多人把“前后端分离部署”和“跨域”搅在一起一看到浏览器控制台报 CORS 错误就跑去后端加注解、加过滤器其实部署阶段绝大多数跨域问题应该是通过 Nginx 反向代理解决的。5.1 为什么本地开发才需要跨域浏览器有个同源策略协议、域名、端口三者完全一致才算同源。本地开发时Vue 开发服务器跑在 5173Vite 默认或 8080SpringBoot 跑在 8080端口不同所以浏览器认为这是跨域请求。这时候要么后端开 CORS要么前端配代理。开发阶段最常见的做法是 Vite 代理// vite.config.js server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }这里changeOrigin: true很关键它让代理转发时把请求的 Host 头改成目标地址后端才不会因为 Host 校验拒绝请求。5.2 生产环境为什么不需要前端跨域了生产环境部署后浏览器访问的是你的域名。前端页面从你域名加载接口请求也发到你域名下的/api/xxx浏览器看到的请求是同源的压根不会触发同源策略所以前端不需要任何跨域配置。真正把请求转发给后端的是 Nginx而 Nginx 这种服务端到服务端的转发不涉及浏览器同源策略属于服务端代理不叫跨域。这也是我前面强调前端请求路径要写成/api的原因——如果写成了http://127.0.0.1:8080浏览器依然会把它当跨域请求处理而且这个地址是内网地址跑到用户浏览器里直接访问不了。5.3 一份可复用的 Nginx server 配置域名解析到服务器后在宝塔的“网站”列表里点击对应站点进入“配置文件”编辑 Nginx 配置。一份能跑通的典型配置如下server { listen 80; # 改成你自己的域名 server_name www.example.com; # 前端 dist 目录 root /www/wwwroot/你的项目名/dist; index index.html; client_max_body_size 50m; location / { try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }这个配置里有两个精髓。第一个是location /里的try_files $uri $uri/ /index.html;——没有它vue-router 的 history 模式刷新页面就会 404因为 Nginx 找不到/login这样的真实路径必须回退到 index.html 让前端路由接管。第二个是location /api/里的proxy_pass http://127.0.0.1:8080;注意末尾没有斜杠。这里有无数人踩坑。规则是这样的如果proxy_pass后面没有 URI 路径也就是没有斜杠转发时会保留原始请求的完整 URI。比如/api/user/list转发成http://127.0.0.1:8080/api/user/list。如果proxy_pass末尾带了/比如http://127.0.0.1:8080/则匹配到的前缀/api/会被替换成/。比如/api/user/list会被转发成http://127.0.0.1:8080/user/list。所以到底用哪种取决于后端接口路径是否带/api前缀。多数情况下后端接口本身就是RequestMapping(/api/user)这种写法那 Nginx 就保持proxy_pass不带斜杠原样转发。如果你的 SpringBoot 接口没有/api前缀而前端统一用/api请求那就需要proxy_pass末尾带斜杠进行路径前缀剥离。这个要结合项目实际不要在网上看到一个配置就复制乱改。5.4 后端到底还开不开 CORS部署阶段由 Nginx 反代解决跨域了那后端CrossOrigin或全局 CORS 配置是否要删掉我的建议是留着无妨但要知道它不起主要作用了。实际场景里你无法保证所有流量都走自己的 Nginx比如调试阶段或第三方系统直接调用后端接口时CORS 配置依然有意义。但要注意如果后端开了非常宽泛的 CORSallowedOriginPatterns(*)并且没有妥善处理预检请求某些情况下反而会让浏览器出现奇怪的双重跨域行为。上线后如果遇到这类问题后端服务日志里会有 OPTIONS 请求记录据此排查即可。最干净的方式还是前端全走/api相对路径后端 CORS 配置保持严格收紧的基本款或干脆关闭。6. 上传产物、配置 SSL 与正式上线配置写好后接下来就是真刀真枪上线了。这里顺序很重要先启动后端再操作 Nginx 和 SSL避免线上出现“页面能开但接口全挂”的尴尬。6.1 启动后端与流量验证回到 server 目录执行./start.sh等几秒后看日志确认启动成功然后在服务器本地用 curl 验证接口是否可用curl -v http://127.0.0.1:8080/api/health 21 | head -20这里用小接口或者健康检查接口测试即可。如果在服务器本机 curl 都失败那基本是后端没起来跟 Nginx 无关先不要去改网络配置。6.2 Nginx 配置生效与常见失败点修改 Nginx 配置后需要验证语法并重载nginx -t nginx -s reload如果nginx -t报错通常是配置文件里有语法问题比如缺少分号、括号没闭合、server_name 后面少了域名。宝塔面板里修改的配置文件在修改时会自动备份出错时可以点“还原”回到之前状态。重载后在浏览器里访问你的域名。此时应该能打开前端首页接口也通了。如果页面打不开先确认域名是否解析成功ping 你的域名 nslookup 你的域名解析不 success 就先解析不要折腾 Nginx。6.3 配置 SSL 证书并强制 HTTPS现在主流浏览器对无 HTTPS 站点越来越不友好所以 SSL 基本是上线必做项。宝塔提供了免费的 Let‘s Encrypt 证书申请操作路径是站点设置 → SSL → Let’s Encrypt勾选域名后申请。申请前提是域名已经解析到这台服务器且 80 端口可访问因为证书申请过程需要验证域名所有权。证书签发成功后宝塔会自动生成 443 端口的 HTTPS 配置。建议在 SSL 面板里打开“强制 HTTPS”这样 HTTP 请求会自动 301 跳转到 HTTPS。跳转后注意后端接口同样会被跳转而接口作为 XHR 请求处理 301 的方式和普通页面不一样某些情况下会引发请求失败。遇到这种问题检查 Nginx 里的跳转配置是否合理或者干脆只对location /跳转、location /api/保持 80 端口放行再从应用层强制要求 HTTPS。但大多数简单场景直接“强制 HTTPS”即可先跑通再优化。6.4 前端静态文件缓存与更新策略上线后修改前端代码是常态但经常出现“改了代码线上还是旧页面”的困扰。原因是浏览器缓存了旧的 JS、CSS。Vue 构建产物的文件名通常带 hash内容变了文件名会变所以理论上不会缓存旧文件。真正容易缓存的是index.html本身。如果它被缓存了浏览器还是加载旧的文件名页面却显示新的文件名列表就会白屏。应对方法是在 Nginx 里对静态资源设置合理的缓存策略对 index.html 设置不缓存或短缓存location /index.html { add_header Cache-Control no-cache, no-store, must-revalidate; } location ~* \.(js|css|png|jpg|gif|svg|woff2?)$ { expires 30d; add_header Cache-Control public, immutable; }这样平时静态资源可以放心让浏览器缓存发布时只要更新了带新 hash 的文件index.html 每次都会回源检查不会出现旧文件残留问题。7. 上线后的验证与故障排查502、404、白屏一条链查到底上线不是终点验证才是。就算按我的流程走项目第一次部署也一定有报错。下面把这些年遇到的高频故障整理成排查链路按步骤走基本能把问题定位到具体层。7.1 分层排查思维我排查问题从来不看表面症状而是先确定“问题出在前端、Nginx 还是后端”这三层中的哪一层。判断方法最有效的是按浏览器工具分页面能打开、接口报 502 → 问题在后端或 Nginx 到后端的链路页面刷新 404 → 问题在 Nginx 的 try_files 配置前端路由页面白屏、控制台资源 404 → 问题在静态资源路径base 配置或 dist 未正确上传记住这个归类往下看会有豁然开朗的感觉。7.2 接口 502 Bad Gateway从几个方向并行排查502 是最常见的部署错误字面意思是“网关收到了但得不到有效响应”放在 Nginx 语境下就是“Nginx 把请求转发给 127.0.0.1:8080但对方没接住”。排查方向如下第一步确认后端进程仍存活ps -ef | grep java ss -tlnp | grep 8080如果 Java 进程不在了看日志找崩溃原因。常见原因是服务器内存不足SpringBoot 启动过程中被系统终止或者nohup启动时没有重定向日志输出丢失后进程被终端挂断。我遇到过最经典的问题是服务器只有 1GB 内存Java 默认堆内存设置导致 OOM方案是加一个-Xmx512m参数限制堆大小保证系统有余量。第二步在服务器本机模拟一次转发curl http://127.0.0.1:8080/api/health如果这一步也 502说明 Nginx 配置的proxy_pass和实际 jar 监听端口不一致或者后端没有监听到 127.0.0.1 而是监听了别的主机名。SpringBoot 默认监听0.0.0.0一般没问题。注意检查是否配置了server.address导致异常。第三步检查 Nginx 错误日志tail -f /www/wwwroot/你的项目名/logs/error.log这里能看到具体的 upstream 连接失败原因比如连接被拒绝、超时等。看到日志再动手比盲目改配置高效得多。7.3 刷新页面 404经典 history 路由问题现象首页能打开但你点点点进到/detail页面再刷新出现 404。这几乎可以断定是 Nginx 缺少try_files。解决方法就是前面配置里的那行location / { try_files $uri $uri/ /index.html; }加上后刷新页面会重新加载 index.html前端路由接管后再匹配/detail页面正常显示。注意后端如果也有/路径拦截别让location /的 try_files 和后面location /api/产生冲突二者路径前缀不同互不干扰。7.4 接口跨域报错仍然出现先看请求实际发到了哪里有时候部署完接口返回 CORS 错误别急着给后端加配置。先打开浏览器开发者工具看 Network 里请求的实际 URL如果请求 URL 是https://你的域名/api/xxx那是同源请求CORS 错误说明 Nginx 没处理好转发比如proxy_pass写错导致 502 之外的服务端错误。如果请求 URL 是https://localhost:8080/api/xxx或http://127.0.0.1:8080/api/xxx那是前端代码里 baseURL 写死了绝对地址需要改回/api重新打包。这个判断一步到位能帮你跳过好多无谓的配置文件修改。7.5 常用命令速查表附上一份平时部署排查用的命令清单按需复制到宝塔终端执行目的命令查看 Java 进程ps -ef | grep java看后端日志实时tail -f /www/wwwroot/你的项目名/server/app.log看 Nginx 错误日志tail -f /www/wwwroot/你的项目名/logs/error.log检查 Nginx 语法nginx -t重载 Nginxnginx -s reload测试后端接口curl http://127.0.0.1:8080/api/health查看端口监听ss -tlnp查看系统内存free -h8. 一些部署细节上的个人体会最后聊点实际操作中的碎片经验。后端日志是排查故障的第一手资料所以从第一天部署开始就要把日志配好。SpringBoot 的logging.file.name或者 logback 配置里指定文件路径比把日志打到 stdout 再重定向更可控。我一般会把日志按日期切片保留最近 30 天避免磁盘被日志撑爆。再说数据库编码。前端界面显示中文乱码很多时候不是前端问题而是数据库建库时默认字符集不是 utf8mb4。宝塔建库时尽量手动指定utf8mb4导入.sql前确认文件本身的编码这个锅经常甩来甩去其实源头最早不要犯。还有一个小细节发布前修改前端代码后记得清一下 CDN 缓存如果挂了 CDN。很多团队部署后反馈“线上没生效”最后发现是 CDN 节点缓存了旧资源。如果暂时没上 CDN就要靠 index.html 不缓存的新增配置这个问题越早规划越好。这套部署流程我前前后后走了很多遍从最开始在服务器上各种踩坑、凌晨起来修 502到现在基本一套流程走完半小时上线中间沉淀下来的经验其实就那一句话先想明白结构再动手操作最后按链路查问题。只要每一步都确认了再走下一步前后端分离项目用宝塔面板部署这件事确实不难。
阅读完成 · 觉得有帮助?