
简介这是一份针对若依前后端分离项目的详细部署文档适合需要在Linux与Windows环境下完成环境搭建、项目上线及排错的Java开发者。文档基于若依框架展开先概述了其前后端技术栈与快速开发能力随后围绕部署全流程给出可操作步骤后台使用Maven打包生成jar前端通过npm构建生成dist目录Linux环境侧重Redis安装与Nginx代理配置Windows环境则将war包及dist文件部署至Tomcat并调整service.xml解决访问路径问题。文档还针对刷新页面出现404、调用百度地图等第三方API时的跨域问题分别梳理了后端CORS配置、前端代理及Nginx反向代理的解决方案便于读者按需选用。资源为1个docx文档大小223KB内容分步骤讲解并附关键配置说明可直接对照实践。已有7761人学习下载对于正在部署若依或其他前后端分离项目的开发者具有实际参考价值。1. 若依前后端分离项目部署为什么总是卡在最后一步若依这套基于 Spring Boot 和 Vue 的免费快速开发平台在本地 IDE 里把后端跑起来、把前端 dev 模式跑起来很多人半小时就做到了但真到部署这一步前端白屏、接口 404、验证码加载不出来这些翻车现场就会排队出现。原因在于它本质上是两个独立进程在配合后端 Java 进程提供接口前端构建出的静态页面由 Web 服务器托管部署做的就是把这套配合按生产要求安排妥当。这篇笔记适合第一次完整部署若依前后端分离项目的开发者也适合要给运维交付可靠步骤的人。我会按环境准备、后端打包、前端构建、Nginx 接入、排错这个顺序写把我踩过的坑直接标出来跟着走完一台干净服务器上两个小时左右能把整套服务跑起来。2. 部署前准备把环境版本和三个组件一次定死若依前后端分离版本不是所有环境都能一把过的先花十分钟把版本对齐后面能省出大量排查时间。我建议在一台干净的 Linux 服务器上做部署以下操作以 CentOS 7 系为例子Ubuntu 或 Debian 的命令差异主要在软件安装方式上目录结构和配置思路完全一致。第一次部署别在原开发机上直接搞打包依赖、端口占用、环境变量互相干扰的问题会让你分不清到底是哪里出错。2.1 版本选型JDK、Node、MySQL 与若依的兼容边界版本为什么是部署第一道坎因为若依后端基于 Spring Boot默认编译目标就是 JDK 1.8用更高版本运行时常会碰到依赖里反射、字节码增强相关的告警甚至启动失败。这不是高版本 JDK 不好而是若依依赖的很多库没有跟着升级没必要为这个冒险。前端是 Vue 2 体系构建时依赖 node-sass 这类原生模块Node 版本太高装依赖那一关就会失败。数据库端 MySQL 5.7 是若依社区用得最多、踩坑最少的版本MySQL 8.0 也完全可以只是要注意连接参数里的时区配置。动手之前先把自己环境里已有的 Java、Node、MySQL、Redis 版本都确认一遍。我常用下面这组命令java -version node -v npm -v mysql --version redis-cli pingredis-cli ping 如果返回 PONG说明 Redis 已启动如果提示连接失败说明服务还没跑起来后面的小节会专门处理。把这些版本信息和下面这张参考表对齐——这不是某份官方文档的强制要求而是我长期部署下来觉得最省事的组合组件推荐版本说明JDK1.8和若依依赖的 Spring Boot 版本最匹配Maven3.6 及以上打后端 jar 用版本太低会遇到依赖解析问题Node14 或 16Vue 2 构建最稳Node 18 大概率装不上 node-sassMySQL5.7 或 8.05.7 最省心8.0 必须处理时区参数Redis5.x 及以上验证码、登录状态、缓存都依赖它我实际见过有人用 JDK 17 硬跑若依后端能启动但登录后菜单接口偶发序列化异常最后排查半天还是换回 JDK 1.8 才稳定。版本这个问题宁可在开始前多花五分钟对齐也别让它留到半夜部署时跳出来。2.2 初始化 MySQL建库、建用户、导入 SQL 脚本若依后端不会自动建库建表第一次部署必须手动导入源码自带的 SQL 脚本。源码的 sql 目录下一般有多个 .sql 文件主库脚本和定时任务相关的脚本是最常见的两个必导项具体文件名以你下载的源码为准。别只导一个就以为完事定时任务相关的表缺失会导致后端启动失败或者定时任务模块一打开就报错。先用命令行登录 MySQL创建若依专用的数据库和用户。我习惯把用户名、密码、库名绑定不直接用 root 跑业务CREATE DATABASE ry_vue DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE USER ry_userlocalhost IDENTIFIED BY Your_StrongPass2024; GRANT ALL PRIVILEGES ON ry_vue.* TO ry_userlocalhost; FLUSH PRIVILEGES;这里库名、用户名、密码只是示例实际部署按你自己的命名习惯来但后面后端配置文件里的数据源信息必须和这里完全一致。执行完登录验证一步mysql -ury_user -p ry_vue。然后导入 SQL 脚本顺序上先主库后定时任务mysql -ury_user -p ry_vue /path/to/ry_main.sql mysql -ury_user -p ry_vue /path/to/quartz.sql字符集统一用 utf8mb4这是避免中文乱码的前提。导入完成后随手查一下表数量确认不是空库mysql -ury_user -p ry_vue -e show tables;。很多人导入后不看结果直接进入后端配置等后端启动时发现没有表相关的报错但登录一直提示用户不存在回头看才发现数据压根没导进去。2.3 准备 Redis启动、密码与连接测试若依后端的验证码、登录状态、缓存都依赖 Redis。Redis 没启动时后端其实可以正常起来但登录会一直提示验证码错误或验证码过期这个坑在第 5 章会展开讲。这里先把环境准备好。系统自带的包管理器装完 Redis 后先确认配置文件里是否设置了 requirepass再启动服务systemctl start redis systemctl enable redis redis-cli ping返回 PONG 说明服务正常。若依后端默认连接 Redis 时密码为空如果你给 Redis 配了密码后面必须同步修改若依后端的配置文件否则后端连不上 Redis。我遇到过这样一个项目开发环境 Redis 有密码部署时忘了在后端配置里同步排查过程绕了大半天最后发现只是密码没对上。这种问题不会在启动时报错只会在登录和缓存读取时表现出各种诡异现象。2.4 准备 Maven 本地仓库镜像配置与依赖缓存后端打包时要下载大量依赖如果网络访问 Maven 中央仓库比较慢打包会长时间卡在 downloading 阶段。常见做法是在 Maven 的 settings.xml 里配置一个镜像仓库。我一般会用一个国内镜像地址能明显缩短打包时间配置方式是在 settings.xml 的 mirrors 节点下加一个 mirrormirror idaliyunmaven/id mirrorOfcentral/mirrorOf urlhttps://maven.aliyun.com/repository/public/url /mirrormirrorOf 设置为 central表示只接管中央仓库的请求不影响其他第三方仓库。镜像地址用你习惯的、验证过可用的即可不一定非这一家。改完 settings.xml 后先执行一次 mvn -version 确认 Maven 能正常读取配置。第一次打包耗时通常较长依赖会在本地仓库缓存第二次以后快很多。这也是为什么我建议部署前先在服务器上把依赖拉一遍别把构建过程留到生产环境上去碰运气。3. 后端打包与启动从源码到可运行 jar 的完整路径后端模块多打包命令相对固定真正容易出错的其实是打包前那几个配置项。若依后端是一个多模块 Maven 工程打包入口在后端核心模块最终可运行的 jar 也在这个模块的 target 目录下。在做任何打包操作之前先去改三处配置数据源、Redis、上传路径。改错了再打包跑起来全是幺蛾子。3.1 修改配置文件数据源、Redis、上传目录三处必改后端配置文件在后端模块的 src/main/resources 下常见的是 application.yml 和 application-druid.yml。三个必改点逐个说。第一是数据源把 URL、用户名、密码改成第 2 章建好的那套第二是 Redis 的连接信息第三是上传文件的保存路径。若依默认把上传文件存在 jar 运行目录的某个子目录里生产环境我通常改到一个固定路径比如 /data/upload。这样以后升级 jar 包用户上传的文件不会被一起清掉。spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.cj.jdbc.Driver druid: url: jdbc:mysql://localhost:3306/ry_vue?useUnicodetruecharacterEncodingutf8zeroDateTimeBehaviorconvertToNulluseSSLtrueserverTimezoneGMT%2B8 username: ry_user password: Your_StrongPass2024 redis: host: localhost port: 6379 password: database: 0 ruoyi: profile: /data/upload数据源 URL 里的 serverTimezoneGMT%2B8 主要是给 MySQL 8.0 用的5.7 不传这个参数通常也没问题。Redis 的 password 字段如果服务没设密码就留空设了就填对应值。ruoyi.profile 决定上传文件的落盘目录这个路径要和后面 Nginx 的 /profile 映射保持一致否则页面上传图片后无法通过浏览器访问。改完配置先确认 /data/upload 目录存在不存在就用 mkdir -p 创建并给运行用户写权限。3.2 用 Maven 打出 jar 包命令与常见参数说明打包在源码根目录执行。Linux 和 macOS 直接在终端跑Windows 用 cmd 或 PowerShell。命令mvn clean package -DskipTestsclean 把之前的编译产物清掉package 负责打包-DskipTests 跳过测试用例项目里测试类很多时这个参数能省不少时间。打完包后到 target 目录确认 jar 文件ls -lh ruoyi-admin/target/*.jar看到几十 MB 的 jar 就对了。这里有一条容易踩的坑target 目录下有时会有带 original 后缀的 jar那是 Spring Boot 重打包前的原始产物不能直接 java -jar 运行。我见过有人把 original 的 jar 拷到服务器启动时报「没有主清单属性」就是这个原因。认准不带 original 的那个。3.3 启动 jarnohup 方式与日志定位把打好的 jar 传到服务器固定目录比如 /opt/ruoyi。然后用 nohup 启动这样断开 SSH 终端进程不会跟着退出。启动前建议建一个普通用户来运行 Java 进程别直接拿 root 跑业务。目录权限给到该用户避免日志文件写不进去。cd /opt/ruoyi nohup java -jar ruoyi-admin.jar --server.port8080 app.log 21 nohup 表示忽略挂断信号 app.log 21 把标准输出和错误输出都写进日志文件最后的 让命令在后台执行。--server.port8080 是命令行覆盖端口的方式优先级高于配置文件里的 server.port。如果 8080 被占用可以临时换一个端口测试但要注意换完后 Nginx 反代地址也要同步改。启动后等二十到三十秒再去看日志Spring Boot 启动需要时间Java 进程在不代表启动完成。3.4 通过日志判断后端是否真的活判断后端启动成功只看进程在不在完全不够。java 进程起来后启动过程十几秒到几十秒中间任何一步出错都可能导致进程退出。把日志当黑匣子任何异常都有迹可循。常用命令tail -f /opt/ruoyi/app.log grep -n Started /opt/ruoyi/app.log grep -n Tomcat started on port /opt/ruoyi/app.log看到类似 Tomcat started on port(s): 8080 (http) 的日志才说明后端真的起来了。如果 grep Started 没结果就看日志最后几十行的异常堆栈。最常见的是数据库连不上、Redis 连不上、端口被占用、表不存在几类堆栈里会把具体原因打出来。后端起来后可以在服务器本机用 curl 探一下接口。直接访问根路径可能返回 404 或空响应那不代表后端挂了更准确的方式是访问若依自带的某个接口路径比如验证码相关接口能返回 JSON 就说明接口通路正常具体路径以你部署的版本实际路由为准。4. 前端构建与 Nginx让页面和接口在同一个域下返回数据前端部署的核心思路是把 Vue 项目构建成静态文件交给 Nginx 托管同时让 Nginx 把接口请求转发给后端 Java 进程。这样浏览器访问页面和接口来自同一个域名天然没有跨域问题。若依开发环境里前端通过 vue.config.js 的代理转发接口生产环境则完全依赖 Nginx。这一步不做好页面出来了也只是半个残废。4.1 前端构建前要改的两个文件前端源码拿到后先看 vue.config.js 和 .env.production 两个文件。vue.config.js 里主要确认 publicPath它决定构建出的静态资源引用路径是绝对路径还是相对路径。若依常见默认写法是 /构建出的 index.html 里引用的 JS 和 CSS 都从根路径开始找如果你要把页面部署在子目录下这里就要改成对应的子目录路径。大多数首次部署不用改但要确认它是 / 而不是 ./否则刷新页面时资源路径容易乱。.env.production 里最关键的是 VUE_APP_BASE_API生产环境构建时前端会把它作为所有接口请求的统一前缀。若依默认一般是 /prod-apiVUE_APP_BASE_API /prod-api这个前缀必须和 Nginx 的 location 规则一一对应。后面 4.3 我会把 Nginx 配置完整写出来你可以直接对照。如果这里改成了别的值Nginx 配置里的 location 也要跟着改否则页面请求的接口路径和 Nginx 转发的路径对不上必出 404。4.2 构建命令与 dist 产物的检查前端构建用 npm。先安装依赖再执行构建。Node 版本建议用 14 或 16原因在第 2 章说过。安装依赖时如果遇到 node-sass 下载失败常见做法是切换 npm 镜像源再重试。构建命令npm install npm run build:prodnpm install 把 package.json 里的依赖装进 node_modules不同网络环境下耗时差别很大耐心等输出结束即可。build:prod 执行生产环境构建产物输出到 dist 目录。如果 package.json 里配置的脚本名不是 build:prod以你拿到的源码里的 scripts 声明为准。构建完成后检查产物ls -lh dist ls dist/static/js | headdist 下应该有 index.html 和 static 目录static 里是打包后的 JS 和 CSS 文件。看到 index.html 存在构建才算成功。如果构建报错先看是不是 node-sass 或 node-gyp 相关错误这类问题绝大部分是 Node 版本或本地编译环境不兼容换到 Node 14 或 16 基本能解决。4.3 Nginx 托管静态文件与 API 反向代理一份能直接用的配置把构建出的 dist 目录传到服务器放到 Nginx 的站点根目录下比如 /usr/share/nginx/html/ruoyi。然后修改 Nginx 配置。下面这份是单站点配置按若依最常见的结构写server { listen 80; server_name your_domain_or_ip; root /usr/share/nginx/html/ruoyi; index index.html; location / { try_files $uri $uri/ /index.html; } location /prod-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 /profile/ { alias /data/upload/; } }root 指向上传的 dist 目录index 指定入口文件。location / 里的 try_files 是 Vue Router history 模式的关键配置它保证访问 /system/user 这类前端路由路径时Nginx 找不到对应文件就回退到 index.html由前端路由接管渲染。location /prod-api/ 把所有以该前缀开头的请求转发给后端 8080proxy_pass 末尾的 / 会把前缀去掉后端收到的就是干净的接口路径。location /profile/ 将上传文件的访问映射到 /data/upload这个配置和 3.1 里 ruoyi.profile 的设置是一对缺了它页面上传的图片会直接 404。改完配置先测语法再重载nginx -t nginx -s reloadnginx -t 输出 syntax is ok 再重载。如果上传大文件记得在 server 块里加 client_max_body_size否则超过默认限制会返回 413这也是若依文件上传功能经常被忽略的一个点。4.4 端口与防火墙部署完为什么还是打不开前端托管好了页面还是打不开最常见的原因不是 Nginx 配置而是防火墙或云服务器的安全策略挡掉了 80 端口。在服务器本机执行 curl 能看到登录页 HTML但外部浏览器打不开基本可以断定是防火墙级别的问题。常见检查命令curl -I http://127.0.0.1/ firewall-cmd --list-all如果 firewall-cmd 里没有 80 端口就放行firewall-cmd --permanent --add-port80/tcp firewall-cmd --reload如果你用的是云服务器还要去控制台的安全组确认入方向是否放行了 80 端口。这个步骤在本地虚拟机里不存在在云上却经常被漏掉。我帮别人排查这类问题时十个里有八个是安全组没放行剩下两个才是 Nginx 配置写错。端口放行之后浏览器访问服务器 IP登录页能正常打开部署工作才算真正到了功能验证阶段。5. 部署避坑白屏、404 与验证码不显示怎么排查这一章整理的是部署若依前后端分离项目时最高频的五个坑也算是我自己的血泪经验。每条按现象、原因、解决三个层次写你可以直接对照自己遇到的情况定位。这些坑单独看都不难难在它们常常同时出现一锅粥地混在一起。5.1 前端打开白屏控制台全是静态资源 404现象浏览器打开首页一片空白F12 控制台的网络标签里 index.html 返回 200但一堆 JS、CSS 文件返回 404。原因通常是 dist 里的资源路径和实际部署目录对不上最常见的是 Nginx root 指错了位置。解决先确认 root 指向的就是 dist 解压后的目录并且 index.html 和 static 目录都在这个 root 下然后在浏览器直接访问一个静态资源路径比如 http://IP/static/js/xxx.js能访问说明路径配置正常不能就检查 root。我遇到最多的场景是dist 目录上传时多套了一层文件夹本应是 /html/ruoyi/index.html结果变成了 /html/ruoyi/dist/index.html而 Nginx root 还指向 /html/ruoyi。把 root 改成 dist 实际所在路径即可。还有一个办法是把 vue.config.js 里的 publicPath 改成 ./让资源走相对路径但这会影响 Vue Router 的 history 模式非必要不建议动。5.2 页面出来了但登录接口 404现象登录页正常显示输入用户名密码点登录接口请求返回 404。原因集中在两个地方前端接口前缀和后端实际路径对不上或者 Nginx 的 location 规则没有正确匹配。解决先打开浏览器 Network 面板看登录请求的完整 URL确认是否以 /prod-api 开头。如果是再到服务器上直接请求后端接口路径确认后端本身是否正常。浏览器请求能到 Nginx 但 Nginx 没转发成功多半是 proxy_pass 写错了后端本身返回 404则检查接口前缀的上下文配置。这里最绕人的是 proxy_pass 末尾是否带 / 的区别。location /prod-api/ 配合 proxy_pass http://127.0.0.1:8080/会把 /prod-api/ 前缀去掉再转发如果 proxy_pass 不带末尾的 /就会把完整路径原样转发给后端。若依默认情况下去掉前缀是正确的改配置时带着这个理解去改就不会稀里糊涂把接口调坏。5.3 验证码图片加载不出来现象登录页看得到验证码图片位置是裂图或空白。原因通常是后端验证码接口没通而验证码接口强依赖 Redis——Redis 取不到缓存或会话时后端会直接报错。解决先看后端日志里有没有 Redis 连接异常堆栈再确认 Redis 服务是否在运行后端配置里的密码是否和实际一致。若依后端启动时不强制校验 Redis 是否可用所以 Redis 挂了后端进程照样活着只有到登录这一步才暴露出来迷惑性很强。验证码加载不出来还有一个容易被忽略的地方Nginx 没有把验证码接口路径送到后端。如果你自定义了接口前缀验证码请求路径也变了记得检查 Nginx 的 location 是否覆盖得住。这个坑排查起来不算难但因为没有直接报错容易让人在前后端代码里来回找。5.4 jar 启动一半就退出日志提示端口被占用现象nohup 启动 jar 后过几秒进程退出了日志里有 Port already in use 或 BindException。原因服务器上对应端口被其他进程占用。解决先查端口占用情况netstat -tlnp | grep 8080 lsof -i:8080找到占用进程的 PID确认它不是需要保留的服务再决定停掉它还是给若依换端口。换端口有两种方式启动时加 --server.port8081或者改 application.yml 里的 server.port。这里埋伏着另一个坑只改了后端端口Nginx 的 proxy_pass 没同步改页面接口全 502。我见过部署时后端端口改成 8081Nginx 还指向 8080排查一整轮才发现是端口没跟上。端口是连接前端和后端的唯一通路改哪边都必须两边一起看。5.5 数据库连接异常表不存在、中文乱码、时区报错现象后端日志报 Table xxx doesnt exist或者登录后列表中文全是问号又或者 MySQL 8.0 下连接时直接报时区错误。原因SQL 脚本没导全、建库字符集不对、连接 URL 缺少字符集或时区参数。解决表不存在回第 2 章把 SQL 脚本完整导一遍确认表数量和源码文档一致中文乱码把建库语句里的字符集明确为 utf8mb4连接 URL 加上 useUnicodetruecharacterEncodingutf8时区报错在 URL 后面补 serverTimezoneGMT%2B8。字符集和时区这类问题很接近一种「数据不对但服务正常」的玄学状态不像端口或 404 那样直观。通用的排查顺序是先看数据库连接 URL 的完整参数再确认表本身的字符集最后看后端日志有没有 SQL 相关的 warning。把三个位置一次性对齐中文乱码基本不会再出现MySQL 8.0 的报错也会一起消失。6. 验证部署结果与两个值得保留的运维习惯6.1 三步验证端口、页面、接口部署完成不能只看登录页能打开。我一般按三步验证第一步确认后端端口在监听第二步确认 Nginx 能返回登录页 HTML第三步模拟接口调用能拿到 JSON 响应。三步命令netstat -tlnp | grep -E (:80|:8080) curl -I http://127.0.0.1/ curl http://127.0.0.1/prod-api/captchaImage第三条里的 /prod-api/captchaImage 是若依常见的验证码接口前缀加方法名如果你部署的版本路由不同以实际后端路由为准。这一步能拿到 JSON说明页面、Nginx、后端、数据库、Redis 整条链路已经打通可以进入功能测试。如果 curl 拿不到数据回到第 5 章按对应现象逐层排查。验证接口时注意看返回体里的 code 字段若依统一返回结构里code 为 200 才是成功其他值说明后端里还有模块级别的问题。6.2 用 systemd 托管后端进程重启不慌日志不乱用 nohup 启动 jar 适合第一次验证生产环境我建议改用 systemd 托管。这样服务器重启后进程能自动拉起日志也统一归 journal 管理不用再到处翻 app.log。写一个简单的服务文件[Unit] DescriptionRuoYi Backend Service Afternetwork.target mysqld.service redis.service [Service] Userruoyi WorkingDirectory/opt/ruoyi ExecStart/usr/bin/java -jar /opt/ruoyi/ruoyi-admin.jar Restartalways RestartSec10 [Install] WantedBymulti-user.targetAfter 里声明依赖 MySQL 和 Redis 服务Restartalways 表示进程异常退出后 10 秒自动拉起。把这个文件放到 /etc/systemd/system/ruoyi.service执行 systemctl daemon-reload 和 systemctl enable --now ruoyi之后用 systemctl status ruoyi 看状态用 journalctl -u ruoyi -f 实时盯日志比 nohup 方式顺手很多。升级 jar 时也是先 systemctl stop ruoyi替换文件再 start整个流程不会留下僵尸进程。另一件我吃了亏才养成的习惯是每次部署前把版本、数据库密码、接口前缀、Nginx 路径四个关键信息记在一个部署清单里升级前先给当前版本的 jar 和 dist 打个备份。没有这些记录出了问题就要到处翻配置隔两三个月再部署第二个环境之前怎么配的全忘了所有排查都得从头来一遍。先跑通部署再把部署清单沉淀成文档是这套流程里性价比最高的一件事也是给你自己留的一颗后悔药。希望帮到你。本文还有配套的精品资源点击获取