简介若依作为一套全面开源的快速开发平台采用Vue、Element UI前端与Spring Boot、Spring Security、Redis、Jwt后端架构广泛用于企业级前后端分离项目。本份部署文档面向需要将若依项目实际部署上线的开发者系统讲解了LinuxNginx与WindowsTomcat两种环境下的完整流程包括jar/war打包、前端dist构建、Redis与Nginx配置、Tomcat访问路径设置并针对部署后常见的菜单打不开、刷新页面404、调用百度地图等第三方API跨域等问题给出了具体排错思路。资源为单个docx文档大小223KB内容按三大部分清晰组织便于对照操作适合具备一定Java与Vue基础、希望完成项目从开发到上线闭环的初中级开发者参考。文档已有7700余人浏览学习实用性强能够帮助读者少走弯路快速完成若依前后端分离项目的部署与调试。1. 若依前后端分离部署从打包到上线的完整路径把若依前后端分离项目从开发机挪到服务器是我见过翻车率最高的一步。开发环境跑得好好的登录页一换到 Linux 加 Nginx 的环境里菜单打不开、登录后白屏、一刷新就 404各种问题轮着来。要说环境多复杂也不见得问题出在部署链路的每一环都可能踩坑而多数教程只写到“把 jar 丢上去启动”就停了。这份部署文档把两条完整路径都梳理清楚了——Linux Nginx 跑 jar 包Windows Tomcat 跑 war 包连 vue.config.js 的路径配置、Tomcat 的 service.xml 修改、刷新 404 的 web.xml 兜底都写到了。适合第一次独立部署若依项目的人也适合给已经上线但频繁改版、被菜单打不开困扰的维护者。2. 打包选型与构建产物部署前先把 jar/war 和 publicPath 定下来2.1 先分清两种部署形态再决定打 jar 还是 war很多人的第一反应是用 IDEA 里的 maven 面板直接点 package打完发现 target 下既有 jar 又有 war就随便拿一个用。这样部署后端大概率要返工因为两种产物的运行原理不一样。若依这个框架本身定位就是快速开发平台前端 Vue 加 Element UI后端 Spring Boot 加 Spring Security、Redis 与 Jwt 权限认证代码生成器一键出前后端代码所以它给出的部署方式也是这套技术栈最常见的两种形态。jar 包是 Spring Boot 内嵌 Tomcat 的产物一个 jar 就是一个独立进程用 java -jar 就能拉起来适合配合 Nginx 一起用。war 包是给外部 Tomcat 用的Tomcat 负责解压部署适合公司已有的 Windows 服务器上装着 Tomcat、不想再引入 Nginx 的场景。判断标准很简单服务器上有 Nginx 就选 jar只有 Tomcat 就选 war。两种方式的差异我整理成了这个对照表对比项Linux NginxWindows Tomcat后端产物jarjava -jar 启动warTomcat 自动解压前端产物dist 目录Nginx 托管dist 目录Tomcat 托管静态资源访问Nginx 的 location /service.xml 的 Context接口转发方式location /prod-api/ 反向代理同源直连不需要代理刷新 404 处理try_files 回退 index.htmlWEB-INF/web.xml 错误页确定好形态后后台代码的打包命令一模一样变的只是 pom.xml 里的一个标签后面两节分开讲。2.2 后台打包mvn clean package 以及从 jar 切 war我用的是 IDEA所以打包直接在 Terminal 里敲命令和用 maven 面板点按钮效果一样但能看清日志# 在项目根目录执行跳过测试以缩短打包时间 mvn clean package -Dmaven.test.skiptrue # 打包完成后去 target 目录确认产物 ls -lh target/*.jarclean 的作用是把上一次的 target 目录清掉避免新旧 class 混在一起产生奇怪问题。package 执行的是编译、打包整条链路-Dmaven.test.skiptrue 跳过单元测试。如果你们的依赖走的是公司私服还需要加上 -s 参数指定 settings.xml否则拉取依赖时会报仓库地址错误。多数版本的项目默认打 jar要在 WindowsTomcat 里用 war 的话修改 pom.xml 的 packaging 标签即可!-- 默认是 jar需要 war 部署时改成 war -- packagingwar/packaging改完之后重新执行 mvn clean packagetarget 下会出现同名 .war 包。需要提醒的是改成 war 后本地启动方式也会变不能再直接跑内置 jar 进程得丢进 Tomcat 才能起服务。文档里没有细说但我一般在改完 packaging 后顺手确认一下 spring-boot-maven-plugin 的 mainClass 配置防止部分版本的插件在打 war 时找不到启动入口。2.3 前端打包npm run build:prod 和 --report 参数前端打包的目标是生成 dist 目录里面是浏览器直接运行的静态文件。命令就是文档里写的这一条# 在 vue 项目根目录执行建议先确认 node_modules 已安装完整 npm run build:prod --report # 确认构建产物重点看 index.html 是否生成 ls -lh dist/index.html--report 参数是这段命令里容易被忽略的地方。它的作用是在打包的同时生成一个资源体积报告你会在前端目录下额外看到 report.html 等文件打开能看到每个 chunk 的体积分布。对部署本身没影响但排查“为什么打包后首屏这么慢”的时候很好用。如果打包过程报内存不足可以加上 NODE_OPTIONS--max-old-space-size4096 再跑一次。跑完命令后重点看 dist 目录里的 index.html打开它的源码你会发现静态资源引用路径有两种形态一种是 /static/js/app.js 这样的绝对根路径一种是 ./static/js/app.js 这样的相对路径。这个差异直接决定你的 dist 丢到服务器哪个位置能正常打开细节在下一节。2.4 vue.config.js 的 publicPath决定打包产物能否到处复用这是部署文档里最值钱的一个配置也是后期“菜单打不开”这类问题的高发点。publicPath 控制打包时写入 index.html 的资源引用前缀。// vue.config.js若依前端项目根目录 module.exports { // 生产环境用相对路径dev 环境保持默认避免本地热更新异常 publicPath: process.env.NODE_ENV production ? ./ : /, // 其他配置项保持不变 }当 publicPath 是 ./ 时index.html 里引用的是相对路径dist 整个目录放到任何子路径下都能打开当它是 / 时资源引用从根路径开始dist 必须放在服务器根路径或者完整匹配这个根路径。文档说的“去掉/之前的.”指的就是把 / 改成 ./。实际部署里这两种写法都合理关键看你的 Nginx 或者 Tomcat 怎么映射目录。如果 Nginx 里直接 location / 对应 dist 目录写 / 没问题如果访问地址本身带了类似 /admin 这样的前缀就必须用 ./ 或者显式写成 /admin/。我从接手项目开始就统一用相对路径省了后面一堆改路径的麻烦。提示publicPath 改动后dist 必须重新生成。只改 vue.config.js 不重新 build浏览器拿到的还是旧资源文件。3. Linux Nginx 部署jar 包、dist 与 redis 的最小上线路径3.1 先装 Redis没它登录都会挂在半路若依的登录验证码和用户 token 都存在 Redis 里Redis 没就位jar 包就算启动了登录的时候也会报连接不上。很多人第一次部署忽略这个前置服务结果在验证码环节就卡住以为是端口防火墙问题最后发现是缓存服务没起来。我习惯先把 Redis 装好并确认它真的能响应# centos 上用 systemctl 启动 redis其他发行版类似 systemctl start redis systemctl enable redis # 确认服务响应返回 PONG 才是真启动 redis-cli pingredis-cli ping 返回 PONG 才代表服务可用。这一步要顺便检查两个配置项bind 和 requirepass。若依后端配置文件里 redis 段的 host、password 必须跟 Redis 实际设置一致否则 jar 包启动正常登录时一样报连接超时或者密码错误。生产环境我一般会在 Redis 配置里设置 requirepass然后把若依配置里的 password 一起改掉。这样不至于因为弱密码被扫描工具盯上排查问题时日志里也不会出现特别明显的报错。3.2 改 nginx.conf静态资源与接口反向代理一起配好Nginx 在整套部署里干两件事一是托管前端 dist 静态文件二是把 /prod-api 开头的接口请求转发给后端的 jar 进程。两件事都要在同一份 nginx.conf 里配好只托管静态文件不管接口转发的话前端登录时会请求不到后端。我一般会在 http 块里新建一个 server 块配置如下server { listen 8080; server_name localhost; # 前端 dist 目录root 写绝对路径location / 匹配所有静态资源 location / { root /data/ruoyi/dist; index index.html; # 关键vue-router history 模式刷新 404 的兜底 try_files $uri $uri/ /index.html; } # 后端接口代理prod-api 是若依默认 context-path location /prod-api/ { proxy_pass http://127.0.0.1:8081/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }这里有两个参数值得展开说。第一个是 try_files $uri $uri/ /index.html意思是浏览器请求一个路径时先去磁盘找对应文件找不到就回退到 index.html交给前端路由自己判断。没有这行vue-router 配了 history 模式你点到二级菜单再刷新一下页面就白白 404 了。第二个是 proxy_pass http://127.0.0.1:8081/ 末尾的斜杠。带斜杠表示转发时把 /prod-api 前缀剥掉后端接口接收到的实际路径是 /login 而不是 /prod-api/login。若依后端的 server.servlet.context-path 默认配置成 /prod-api 时Nginx 转发时就要带上前缀写法改成 proxy_pass http://127.0.0.1:8081/prod-api/。这个斜杠问题很多人第一次配会折在这里文档里没细说但实际部署大概率要踩一次。注意proxy_pass 末尾是否带斜杠取决于后端 context-path。若依默认 /prod-api 时两边配置不一致就会让接口请求全部失败。3.3 启动 jar 包nohup、日志和进程管理jar 包传到 Linux 之后直接用 java -jar 启动的话窗口一关进程就没了。部署文档里用的是 nohup 方式这条命令值得把每个部分拆开理解# 在 jar 包所在目录执行msg.log 会生成在当前目录 nohup java -jar ruoyi-admin.jar msg.log 21 # 查看启动过程中的日志 tail -f msg.lognohup 的意思是让进程忽略挂断信号终端关闭也不退出后面的 msg.log 把标准输出写入文件21 把错误输出也合并到同一个文件保证日志完整最后一个 让整个命令进入后台。拆开看就明白为什么很多人说“jar 起来了一下就没了”——八成是少了 nohup 或者少了 。启动之后我一般先 tail -f msg.log 盯几秒看到 Tomcat started 或者若依的启动横幅才算稳。如果端口被占用日志里会出现 bind 异常换端口或者把旧进程杀掉再启。生产环境里 JVM 参数我习惯带内存上限java -Xms512m -Xmx1024m -jar ruoyi-admin.jarJava 8 之后还可以追加 -XX:UseG1GC日志量大的时候内存波动会小一些。3.4 启动 Nginx 与上线自检配置文件改完先做语法检查再 reload# 检查配置语法 nginx -t # 重新加载配置 nginx -s reloadnginx -t 会输出 configuration file test is successful 才算过。reload 是平滑重载不用重启整个 Nginx 服务。这里有个小习惯我每次 reload 之前都会先确认一下当前调用的 nginx 是哪个路径下的避免系统里装了多个 nginx 版本命令找错实例改了配置半天不生效。然后就是浏览器输入 IP 加端口访问。第一次上线我会按顺序检查页面标题和布局出来没有登录页验证码能不能显示验证码输入后能否登录通过进入系统后菜单能不能展开随便打开一个菜单刷新一下会不会 404。这一条跑完部署链路就算真正通了。4. Windows Tomcat 部署war 包和两个“看不见”的配置文件4.1 为什么 Windows 部署要打 war 包Windows 服务器上常见的 Java Web 运行环境就是 TomcatTomcat 本身是 Servlet 容器war 包是它的标准部署单元。把打包类型从 jar 改成 war解压部署这些事就交给 Tomcat 去处理不需要 java -jar 手动拉进程。这样你跟运维之间的协作边界也清晰Tomcat 服务由系统运维管应用代码更新就是往 webapps 里丢 war 包。改完 pom.xml 的 packaging 标签后重新打包把生成的 war 复制到 Tomcat 的 webapps 目录下。命名阶段有个值得注意的约定把 war 包改名为 prod-api.war这样 Tomcat 解压后会自动生成 prod-api 目录访问路径就是 ip:端口/prod-api。这个命名最好和后端的 context-path 保持一致后面前端接口调用不容易出歧义。更新版本时先删掉旧解压目录再放新包不然新旧文件混在一起可能会出现菜单权限数据对不上的怪问题。4.2 service.xml 的 Host 节点登录成功却白屏的根源Windows 部署最常见的故障是登录页能打开账号密码也能登录但登录完跳转后页面一片空白。文档里提到的修改 service.xml 就是要解决这个问题的。Tomcat 默认情况下访问 ip:端口 走的是 ROOT 应用你的前端 dist 没有映射到根路径路由跳转时就找不到对应的静态页面。解决办法是在 Host 节点下添加一个 Context 配置Host namelocalhost appBasewebapps unpackWARstrue autoDeploytrue !-- 把 dist 映射到访问根路径docBase 写成绝对路径最稳 -- Context path/ docBaseD:/tomcat/webapps/dist reloadabletrue crossContexttrue/Context /Hostpath/ 表示访问根路径时直接交给 docBase 指定的目录处理。docBase 我建议写绝对路径相对路径在 Tomcat 重启时容易解析出偏差。reloadabletrue 的意思是 dist 目录里的文件有变化时自动重新加载开发测试阶段方便生产环境一般改成 false减少不必要的资源扫描。crossContext 这个属性保留默认即可大多数项目用不到。有的场景也可以不配这个 Context直接把 dist 内容全部复制到 webapps/ROOT 下面效果一样。我一般不动 ROOT 目录怕和 Tomcat 自带管理页面冲突用 Context 配置的方式更干净也方便一个 Tomcat 实例挂多个前端应用。4.3 刷新 404 的补救WEB-INF/web.xmlTomcat 环境下登录进去之后点菜单正常但只要一按 F5 刷新大概率会得到 404 页面。原因是 vue-router 用了 history 模式浏览器把 /system/user 这类路径当作真实地址去请求 TomcatTomcat 找不到对应的物理文件就返回 404。解法是在 dist 目录下新建 WEB-INF 文件夹放入 web.xml把 404 错误统一指向 index.html。文档给出的 web.xml 配置是我验证过能用的完整保留如下?xml version1.0 encodingUTF-8? web-app xmlnshttp://xmlns.jcp.org/xml/ns/javaee xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd version3.1 metadata-completetrue display-nameRouter for Tomcat/display-name error-page error-code404/error-code location/index.html/location /error-page /web-apperror-page 的意思很直白当 Tomcat 遇到 404 时不再返回默认错误页而是把请求转发给 /index.html。index.html 里的前端路由启动后会根据当前 URL 自己判断该渲染哪个页面路由不对就显示系统自带的 404 页面路由对就正常渲染。注意这个 web.xml 必须放在 dist/WEB-INF 下Tomcat 才会把它识别为这个应用的一部分放错位置不会生效。注意web.xml 的 schema 版本要和 Tomcat 主版本匹配Tomcat 7 建议用 3.0Tomcat 8 及以上再用 3.1。4.4 Tomcat 启动与访问路径确认Tomcat 的启动端口在 service.xml 里的 Connector 节点配置默认 8080。部署完成后浏览器直接访问 ip:8080 就能看到登录页。如果你把 war 改名为 prod-api访问路径是 ip:8080/prod-api前端页面和接口就在同一个上下文下接口请求也要相应调整。这里有个和 LinuxNginx 部署的差异点在 Tomcat 方案里没有 Nginx 做反向代理前端页面和接口是同一个端口、同一个应用下访问的所以基本不存在跨域问题。若依前端调用后端接口的默认前缀是 /prod-api正好对应 war 解压后的 prod-api 目录这一层对应关系在浏览器里抓包时最容易被忽略。启动 Tomcat 后我一般先看 logs/catalina.out 的末尾几行确认 prod-api.war 解压成功且没有报错接着再打开浏览器走一遍第 3.4 节的自检顺序。5. 部署后的常见问题排查五个高频坑的现象、原因与修复5.1 菜单打不开publicPath 从“/”变成“./”就自愈现象第一次打包部署没问题后期修改了一些文件或者菜单权限重新构建部署上去后页面能打开但菜单点击完全没反应控制台里能看到一堆资源加载失败。原因这多半是构建配置里的 publicPath 在生产环境被设成了 /而这次部署的目录和上次不完全一致比如从根路径换到了带前缀的路径导致 index.html 引用的静态资源找不到。解决回到前端项目修改 vue.config.js 的 publicPath把 / 改成 ./重新 build 一次再部署。// vue.config.js 修改前 publicPath: /, // 修改后相对路径dist 放到任何目录都能自适应 publicPath: ./,我遇到这种问题从来不去改 Nginx 或者 Tomcat 的映射关系改 publicPath 重新打包的成本最低而且一劳永逸。注意修改后要清一下浏览器缓存否则可能拿到旧的 index.html验证半天以为没生效。5.2 登录成功但跳转空白页Tomcat 的 Context 没配对现象WindowsTomcat 部署后登录页正常显示验证码能出输入账号密码也能登录但登录成功后浏览器地址变成了 ip:端口/index页面却是白屏控制台不报接口错误。原因dist 目录没有映射到 Tomcat 的访问根路径。前端路由跳转时访问的是根路径下的 index.html但 Tomcat 默认把没有 Context 的路径交给了 ROOT 应用返回的内容不是前端页面。解决在 service.xml 的 Host 节点下加 Context 配置把 docBase 指向 dist 目录path 设置为 /。懒得改配置文件的话把 dist 内容全部清进 webapps/ROOT 也是同样效果。改完重启 Tomcat再登录一次确认跳转正常。5.3 刷新就 404前端路由缺少服务端回退现象登录进入系统后页面切换正常但只要按 F5 或直接刷新当前 URL就会出一个 404 页面。刷新一次 404再从登录页进去又正常。原因若依生产环境用的是 Vue Router 的 history 模式URL 是真实路径形式服务端Nginx 或 Tomcat找不到对应的物理文件时就会返回 404。解决按部署环境区分处理。LinuxNginx 方案里在 location / 里加一行 try_files $uri $uri/ /index.html。WindowsTomcat 方案里在 dist 目录下建立 WEB-INF 目录并写入 web.xml配置 404 错误页指向 index.html。两个操作的本质都是把不存在的路径统一回退到前端入口。5.4 接口返回正常但页面白屏静态资源路径不对现象打开页面后Network 面板里接口数据全部正常返回登录接口 200菜单接口 200但页面就是渲染不出来css 和 js 文件一堆 404。原因接口正常说明后端链路没问题白屏就是前端资源加载失败。常见的是 publicPath 用了绝对路径 /而实际页面挂在 ip:8080/prod-api 这样的子路径下浏览器根据根路径去找 static 资源时找不到。解决先按住 Ctrl 点击页面空白处打开源码看 index.html 里的 script src 前缀长什么样再到 Nginx 或 Tomcat 里确认实际部署层级。若依项目最稳妥的改法还是把 publicPath 设为相对路径 ./重新打包。要注意的是这个问题在 Linux 方案里如果 Nginx root 配的就是 dist 目录绝对路径反而没问题只有在子路径部署时才会暴露。5.5 验证码登录偶发失败Redis 状态与密码不一致现象jar 或 war 明明都正常启动了但登录时验证码经常提示错误或者第一次登录成功刷新之后 token 又失效。查看后端日志能看到和 redis 相关的连接异常。原因若依的验证码和用户 token 都存在 Redis 里。Redis 没启动时验证码存不进去也取不出来自然一直报错Redis 密码和后端配置文件不一致时表现更隐蔽有时候能连上请求一多就超时。解决先执行 redis-cli ping 确认 Redis 在跑再看后端配置文件里 redis 的 host、port、password 与 Redis 实际配置是否一致。另外如果 Redis 设置了 maxmemory 且淘汰策略比较激进验证码可能被提前清理检查一下 maxmemory-policy保留默认的 noeviction 或者改成 allkeys-lru 都行。注意改完配置要重启对应服务Redis 配置变更不是改完立即全部生效。6. 跨域处理与固定部署习惯从 CORS 配置到上线自检顺序调用第三方 API 的跨域问题本质是浏览器同源策略在拦路。前端部署在公司的业务域名下第三方接口在别人家的域名下两边不同源浏览器就会把请求拦下来报 CORS error。区分问题属于哪一边有个简单方法看 Network 面板里那条请求是根本没发出去还是发出了但响应被浏览器拦截。若依后端一般保留一个全局 CORS 配置类我习惯在这里统一处理自有接口的跨域// 全局 CORS 配置解决自有后端接口的跨域问题 Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowCredentials(true) .maxAge(3600); } }allowedOriginPatterns() 配合 allowCredentials(true) 时不能写成 allowedOrigins()这是不少人在配置 CORS 时栽过的跟头。第三方地图类 API 的跨域没法在后端直接配置解决常见做法是让后端或者 Nginx 转发一次请求绕过浏览器的同源限制。部署这件事我从踩过几次坑之后养成了一个固定习惯每次上线前按“确认 Redis → 确认 Nginx 配置语法 → 确认接口连通 → 刷新页面验证路由回退”的顺序强制走一遍改过前端代码就先把 publicPath 检查一次改过后端接口就先把 context-path 和代理路径对一遍。这套流程看似简单但它能拦截掉大部分部署路上的幺蛾子。如果你正打算部署若依或者已经在为这些故障头疼这份部署文档值得照着完整过一遍。希望帮到你。本文还有配套的精品资源点击获取