RuoYi这套脚手架在后台管理类项目的交付里出现频率实在太高了,前后端分离、RBAC权限、代码生成器、定时任务全都自带,基本就是“开箱即用”的代名词。但“开箱即用”不等于“部署顺利”,我前前后后在不同环境里部署过七八次这套系统,从单机演示环境到内网隔离环境都碰过,踩过的坑攒了不少。这篇文章就是一份完整的部署笔记,从环境选型、后端打包、数据库初始化、前端构建到Nginx落地和进程守护,把每一步的实操命令和背后的设计逻辑都写清楚。不管是第一次部署RuoYi的初学者,还是已经在本地跑通、准备上生产的老手,这份笔记都能帮你少走不少弯路。
1. 部署前先想清楚:版本组合与环境规划
1.1 为什么这套框架适合做内部管理系统的基座
RuoYi解决的是后台管理系统里最重复的那部分工作:用户管理、角色权限、菜单路由、操作日志、字典管理,这些模块在几乎所有管理后台里都是必需的,但每个项目都从零写一遍纯属浪费时间。它的权限模型是基于RBAC(基于角色的访问控制)实现的,用户挂角色、角色挂菜单权限,前端路由根据权限动态生成,后端接口通过注解做细粒度校验,这套机制在中小型项目里完全够用。再加上内置的代码生成器,可以从数据库表直接生成Java代码、Vue页面和SQL菜单脚本,新模块落地速度非常快。
所以它特别适合这几类场景:公司内部运营后台、中小型企业的管理系统、外包交付的基础框架,以及个人用来搭建自己的项目脚手架。我见过的实际项目中,很多人并不是冲着它的高并发能力去的,而是看中它把权限和基础功能都封装好了,团队只需要专注业务模块的开发就行。理解了这一点,你在部署时就不会纠结于“并发扛不扛得住”这种问题,而是要更关注“怎么让环境干净、配置正确、跑起来稳定”。
1.2 一套不容易出错的版本组合
RuoYi有两个常见的分支路线,一个是单体版本的RuoYi,一个是前后端分离的RuoYi-Vue,现在大部分新项目都走前后端分离这条路线,所以本文以这条路线为准。技术栈是Spring Boot后端加Vue前端,配套MySQL数据库和Redis缓存。下面这组版本组合我在多个环境里验证过,稳定性比较好:
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| JDK | 1.8 | 框架默认编译级别是Java 8,换更高的版本需要改配置,没必要冒这个险 |
| Maven | 3.6.x | 3.8以上在某些镜像源下会有仓库配置兼容问题 |
| Node.js | 14.x 或 16.x | 前端项目是基于Vue 2的,Node版本太高会导致依赖编译报错 |
| MySQL | 5.7 或 8.0 | 8.0需注意驱动版本,框架自带的驱动已兼容 |
| Redis | 5.x 及以上 | 只用到基础缓存和会话功能,单机Redis即可 |
| Nginx | 1.20+ | 前端静态文件服务,同时做接口反向代理 |
服务器配置方面,如果是演示环境或者并发量很小的内部系统,2核4G就足够了。生产环境建议4核8G起,因为除了后端进程,MySQL和Redis也要占内存。部署目录我习惯这样规划,把前后端和中间件分开,后续排查问题会方便很多:
/opt/ruoyi/ ├── backend/ # 后端jar包存放目录 ├── frontend/ # 前端dist静态文件目录 ├── logs/ # 日志统一存放 └── scripts/ # 启动、备份脚本这里有个容易忽略的点:内网部署时,Maven中央仓库和npm官方源可能访问超时,导致打包卡在下载依赖这一步。所以部署前一定要先确认好内网可用的仓库镜像地址,Maven的settings.xml里配置好私服或镜像,npm配置好registry,再开始打包。我见过有人在一个环境里打包打了整整一天,最后发现是依赖下载超时。
2. 后端编译打包:多模块工程的构建细节
2.1 源码目录结构速览
拿到源码后,先别急着执行打包命令,花两分钟把目录结构搞清楚。标准的RuoYi-Vue后端是一个Maven多模块工程,核心模块有:
ruoyi-admin:启动模块,包含启动类和main方法,最终打出来的可执行jar就是从这里出的ruoyi-framework:框架核心,配置类、拦截器、权限处理都在这里ruoyi-system:系统业务模块,用户、角色、菜单等业务代码ruoyi-quartz:定时任务模块ruoyi-generator:代码生成模块ruoyi-common:公共工具类
这些模块之间的依赖关系是编译期自动处理的,你不需要手动逐个打包,只需要在根目录执行Maven命令,它会按依赖顺序构建所有模块。执行构建时,建议跳过测试用例,因为部分测试用例需要连接数据库和Redis,在构建机上没有这些环境的话会直接报错。
# 在项目根目录执行 mvn clean package -Dmaven.test.skip=true构建完成后,可运行的jar包在ruoyi-admin/target/目录下,文件名通常是ruoyi-admin.jar。这里的命名要留意一下,有些版本的pom文件里配置了finalName,打出来的包名可能不一样,你可以直接在target目录下看到实际的jar名称。
2.2 配置文件改哪几个地方
RuoYi的配置都集中在ruoyi-admin/src/main/resources/目录下,主要改两个文件。第一个是application.yml,这里配置了服务端口、应用名称、profiles激活状态等。默认端口是8080,生产环境如果不想直接用默认端口,可以改成你规划好的端口。另一个是application-druid.yml,这里配置了数据源和Redis的连接信息。
# application-druid.yml 关键配置 spring: datasource: druid: url: jdbc:mysql://你的数据库地址:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: 数据库用户名 password: 数据库密码 redis: host: Redis地址 port: 6379 password: Redis密码数据源URL里有几个参数值得说一下。characterEncoding=utf8保证中文存取不乱码,serverTimezone=GMT+8解决MySQL 8.0时区问题,useSSL=true在部分数据库版本下必须显式声明,否则连接会被拒绝。如果你用的是MySQL 8.0,驱动已经是com.mysql.cj.jdbc.Driver,框架自带的就是这个,不需要额外处理。
Redis的密码如果没设,password字段留空或注释掉都可以。这里有个坑:某些版本里spring.redis.password如果不设置,会读取一个空字符串去做认证,导致连不上有密码的Redis,反过来也一样。所以务必保证配置文件里的密码和实际Redis密码完全一致,包括前后空格。
2.3 本地验证打包产物
编译出jar之后,不要直接传到服务器,先在本地(或构建机)启动一次验证基本功能。执行方式很简单:
java -jar ruoyi-admin.jar启动日志里如果能看到类似“Started RuoYiApplication”的字样,说明后端基本没问题。接着访问http://服务器IP:端口,如果配置正确,浏览器里能看到Swagger或默认的接口响应页面。不通过Nginx直接访问时,登录接口/login会返回一个JSON,里面包含验证码信息,说明后端已经正常工作了,可以收尾打包。
这一步能帮你把问题隔离在“构建”和“运行”两个阶段。如果本地启动都报错,就不要往服务器上传了,先排查代码或配置问题,否则到服务器上才发现问题,排查链路会拉长好几倍。
3. 数据库与中间件初始化:最容易翻车的一环
3.1 SQL脚本的导入顺序和字符集
RuoYi的SQL脚本在源码的sql/目录下,通常包含一个主库脚本(类似ry_2024.sql)和一个可选的quartz.sql(定时任务表)。导入MySQL之前,先确认目标库的字符集。我推荐建库时显式指定字符集,避免默认字符集不一致导致中文乱码:
CREATE DATABASE IF NOT EXISTS `ry-vue` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;用utf8mb4而不是utf8的原因很简单:utf8在MySQL里最大只能存3字节的字符,遇到emoji或生僻字会报错或乱码,utf8mb4是完整的4字节字符集,兼容所有UTF-8字符。RuoYi自带脚本用的是标准SQL,两种字符集都能导入,但后续业务表如果涉及emoji,推荐使用utf8mb4。
导入顺序上,先导入主脚本,再导入quartz脚本。有些老版本项目里主脚本已经包含了quartz相关表,重复导入会报Table already exists,遇到这种情况忽略即可,说明表已经存在了。导入命令:
mysql -u用户名 -p 数据库名 < /path/to/ry_2024.sql mysql -u用户名 -p 数据库名 < /path/to/quartz.sql导入完成后,重点检查三张表:sys_user(用户表)、sys_role(角色表)、sys_menu(菜单权限表)。RuoYi默认的管理员账号是admin,密码是admin123,首次登录后系统会强制要求修改密码。如果你导入的SQL里admin账号不存在或者密码不正确,可以手动往sys_user表里插入一条记录的哈希值,但更省事的做法是删库重导,不要手动去改密码哈希,很容易改错格式导致登录时校验失败,别问我怎么知道的。
3.2 Redis初始化的隐形麻烦
RuoYi把验证码、会话token、部分缓存数据都放在Redis里,Redis没准备好,后端即使能启动,登录接口也会报错。部署Redis时,有两点比较容易被忽略。
第一点是Redis的密码配置。如果Redis设置了密码,记住两个地方都要改:后端application-druid.yml里的password字段,以及Redis配置文件redis.conf里的requirepass。如果你只是改了Redis的密码而忘了改后端配置,表现就是登录时报“无法获取验证码”或“缓存服务异常”,日志里能看到NOAUTH Authentication required的报错。
第二点是Redis的持久化策略。生产环境建议开启AOF持久化,这样Redis重启后缓存数据不会全部丢失。虽然RuoYi对缓存丢失的容忍度较高(重建登录会话就行),但如果系统里存了业务缓存数据,关闭持久化的Redis一重启,用户那边就会体验到大面积重新登录和缓存失效。Redis层面不要偷懒,该开的持久化要开。
# redis.conf 关键配置 requirepass 你的Redis密码 appendonly yes appendfilename "appendonly.aof"数据库和Redis都初始化完成后,可以启动后端做一个最简单的联调:请求验证码接口,能看到Redis里新增了一个验证码的key,说明缓存链路是通的。到这里,后端部分基本就稳了。
4. 前端构建与Nginx落地:路由模式是重点
4.1 生产环境构建的参数调整
前端部分的源码目录结构和普通Vue 2项目一致,核心目录是src/,构建配置文件在项目根目录的vue.config.js和public/下。生产构建前,最好检查一下vue.config.js里的publicPath,如果部署在域名根路径下,保持默认的'/'即可;如果部署在子路径下(比如http://域名/ruoyi/),需要改成对应子路径,否则前端静态资源404。
依赖安装时,如果npm下载速度慢,可以临时指定镜像源,或者用本地的离线缓存。这一步属于常规操作,我建议把npm仓库配好再构建,免得反复超时。
npm install npm run build:prod构建完成后,产物在dist/目录下。这个目录里的文件就是所有前端静态资源,直接整个目录拷贝到服务器上。注意点:dist目录每次构建都会重新生成,不要手动修改里面的文件,所有的修改都应该在源码里完成后再重新构建,否则下一个人拉取代码构建后你的手动修改就丢了。
4.2 Nginx配置里最关键的一行
前端静态文件部署本身不难,把dist目录放到Nginx的站点目录下就可以访问。但RuoYi的前端路由是基于Vue Router的history模式,不是hash模式,这意味着用户访问/system/user这类子路径时,Nginx如果找不到对应的物理文件,就会返回404。解决办法是配置一个回退规则:
server { listen 80; server_name your-domain.com; # 前端静态文件 root /opt/ruoyi/frontend; index index.html; # history路由回退,解决刷新404 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; } }上面配置里最核心的就是try_files $uri $uri/ /index.html这一行。它的逻辑是:先尝试按当前路径找文件,找不到就看目录,再找不到就把请求转给index.html,由前端路由接管。我第一次部署时忘了加这行,页面还停留在/能打开,换个菜单页面再刷新就直接白屏404,排查了半天才反应过来是history路由的问题。
4.3 接口反向代理的路径处理
RuoYi前端的接口请求默认带/prod-api/前缀,Nginx需要把这部分请求转发到后端,并且把前缀去掉。上面配置里proxy_pass http://127.0.0.1:8080/;结尾带斜杠,意思就是去掉匹配到的/prod-api/前缀,把剩余的路径拼到后端地址后面。比如请求/prod-api/login,实际转发到后端的是http://127.0.0.1:8080/login。
如果你的后端端口改了,或者后端不在本机,记得修改这里的地址。另外,生产环境建议加上proxy_set_header这几行,把客户端的真实IP和协议信息传给后端。RuoYi的日志模块会记录操作日志,如果没传X-Real-IP,日志里看到的所有操作IP都会变成Nginx所在机器的IP,排查安全问题时少了一个有用维度。
配好后,执行nginx -t检查配置语法,再nginx -s reload重载配置,然后访问你的域名,能看到登录页就说明前后端链路已经通了。用默认账号admin/admin123登录,走一遍验证码校验和菜单加载,这一步能过,部署的主流流程就算完成了。
5. 服务化与管理:让进程稳定运行的关键
5.1 用systemd托管后端进程
很多人部署Java应用的习惯是用nohup java -jar xxx.jar &启动,这个方式在临时调试时没问题,但生产环境有几个弊端:开机不会自动启动、进程挂了没人拉起来、日志管理全靠重定向。我建议用systemd把后端封装成系统服务,一个简单的unit文件就能解决自动重启和开机自启的问题。
# /etc/systemd/system/ruoyi.service [Unit] Description=RuoYi Backend Service After=network.target mysql.service redis.service [Service] Type=simple User=root WorkingDirectory=/opt/ruoyi/backend ExecStart=/usr/bin/java -Xms512m -Xmx1024m -jar /opt/ruoyi/backend/ruoyi-admin.jar Restart=on-failure RestartSec=10 StandardOutput=append:/opt/ruoyi/logs/backend.log StandardError=append:/opt/ruoyi/logs/backend-error.log [Install] WantedBy=multi-user.target这个unit文件里几点值得注意:Restart=on-failure表示只在异常退出时自动重启,正常停止或手动重启不会干扰操作;RestartSec=10是设置重启前等待10秒,避免进程还没释放端口就强行启动导致冲突;StandardOutput和StandardError分别指向两个日志文件,错误和正常日志分开,排查问题更方便。
文件写好后,依次执行:
systemctl daemon-reload systemctl enable ruoyi systemctl start ruoyi systemctl status ruoyienable让服务开机自启,start立即启动,status查看运行状态。以后发布新版本时,只需要替换jar包,然后systemctl restart ruoyi即可,干净利落。
5.2 上线自检清单
部署完成并不是“能登录就行”,以下这些检查项建议每一项都过一遍,至少能帮你提前发现一半以上的潜在故障。
| 检查项 | 验证方式 | 常见问题 |
|---|---|---|
| 后端进程状态 | systemctl status ruoyi | 进程反复重启、端口被占用 |
| 接口连通性 | 浏览器访问登录接口 | 502、504、连接拒绝 |
| 定时任务是否开启 | 后端日志查看Quartz初始化 | 定时任务不执行 |
| 文件上传目录 | 尝试上传一张图片 | 上传后找不到文件或访问404 |
| 日志滚动策略 | 查看logback配置 | 日志文件无限增长,占满磁盘 |
| 数据库备份 | 执行一条mysqldump命令 | 备份失败、权限不足 |
| 前端刷新页面 | 菜单页面按F5 | 404白屏,检查try_files |
特别提一下定时任务和文件上传这两个点。RuoYi的定时任务基于Quartz,如果你在系统配置里启用了定时任务,但检查时发现任务不触发,大概率是数据库里qrtz_*表的配置和代码里调度器配置不一致,或者后端启动顺序晚于数据库初始化,导致任务表加载失败。文件上传方面,RuoYi默认的本地存储路径需要提前创建好,并保证运行用户有读写权限,否则上传接口会报“系统异常,请联系管理员”这种含混不清的错误,日志里才能看到真正的FileNotFoundException。
5.3 Nginx的缓存和压缩优化
静态资源的访问性能,主要靠Nginx层面的缓存和压缩。RuoYi前端构建出的JS和CSS文件名带哈希值,内容变了文件名也会变,所以可以放心设长缓存。图片和字体等资源同理。这样配置后,用户再次访问页面时静态资源走本地缓存,明显快很多。
location /static/ { expires 30d; add_header Cache-Control "public, no-transform"; } gzip on; gzip_min_length 1k; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss image/svg+xml;gzip压缩对接口返回的JSON效果非常明显,一个原本几十KB的列表数据压完可能只有几KB,前端渲染速度直接提升一个档次。但对于后端线程池本身,RuoYi在application.yml里配置了Tomcat的max-threads,默认是200,内部系统够用了,不建议盲目调大,线程切来切去反而降低处理效率。
6. 踩过的坑汇总与最后的建议
6.1 高频部署问题对照表
把部署过程中遇到的高频问题汇总成表,希望能帮你在报错时更快定位:
| 故障现象 | 大概率原因 | 解决方向 |
|---|---|---|
| 后端启动失败,日志提示数据库连接失败 | 数据库地址、用户名、密码错误 | 检查application-druid.yml |
| 端口无法访问 | 云安全组、防火墙没放行 | 检查iptables和云控制台安全组规则 |
| 前端访问正常,接口全部401 | 前端请求前缀与Nginx代理不匹配 | 检查/prod-api/配置 |
| 验证码接口报缓存异常 | Redis连接失败或密码错误 | 检查application-druid.yml和Redis |
| 页面刷新404 | history路由未配置try_files | 补上try_files $uri $uri/ /index.html; |
| 上传文件失败 | 目录不存在或无写权限 | 创建目录并chmod |
| 定时任务不执行 | Quartz表数据问题 | 重新初始化quartz.sql |
6.2 服务器安全层面的额外措施
这部分属于“默认最好做”的增强项。新部署的RuoYi系统,管理员账号也是默认的admin/admin123,这个密码虽然首次登录会强制修改,但如果你在测试阶段把它当演示系统丢在公网服务器上,别人可能用默认密码批量扫描。建议部署完成后立刻登录后台,修改admin密码,关闭或限制定时任务接口的外网访问,并且在生产环境的数据库里禁用或加密保存Druid监控页面的访问地址。
Nginx层面可以为敏感路径加一个简单的访问控制。比如/druid/index.html这类监控页面,通过location加白名单IP来实现限制,防止数据源连接信息和管理界面暴露到公网。数据库层面,授权时应该用最小权限,不要直接用root连接应用,创建一个专用账号并仅授予目标库的增删改查权限。
6.3 后续扩展的方向
这套部署流程跑通之后,后续可以按照团队需求逐步扩展。比如把后端打包做成流水线,每次代码提交后自动构建jar并部署;前端构建也可以接入同一套流水线,构建完后自动同步dist目录到Nginx站点下。这些改造的核心还是依赖这里已经验证过的部署链路,只是把人工操作自动化了。
最后分享一点个人体会:RuoYi这类成熟框架的部署,最大的风险往往不是框架本身的代码质量,而是环境差异和配置细节。同一个版本的RuoYi,在干净的CentOS上可能半小时就能跑起来,在有其他服务占用的机器上可能折腾一整天。所以做事的方式很重要,部署之前先检查端口、检查依赖、检查网络,把环境状态确认清楚再动手,效率反而最高。这套笔记里的思路和命令,我自己在多个项目里反复用过,按这个流程走,你大概率也能一次跑通。