2025年初,我接手了一个SaaS后台管理项目。团队就3个人,工期紧、需求多,老板丢下一句话:"两周内出第一版。"
当时脑子里第一个蹦出来的就是若依。
别笑,我知道很多人对若依有各种看法,但它的星标不会骗人——GitHub 上将近 30k star,Gitee 上更是常年霸榜。社区活跃、文档齐全、教程满网飞,对一个被工期追着跑的小团队来说,这就是最快落地的选择。
建完数据库表,打开代码生成器,勾上字段,点一下"生成",Controller、Service、Mapper、Vue页面全部到位。两天,我就把用户管理、角色管理、菜单权限、部门管理的基础框架全部搭好了。看着页面上那一排排整齐的功能菜单,我跟自己说:这次稳了。
第一个月,一切顺利得不像话。
用户管理、角色管理、菜单权限,若依全部开箱即用。前端用的是若依的 Vue3 版本,Element Plus 组件库,界面清爽够用。权限注解 @PreAuthorize("@ss.hasPermi('system:user:edit')") 往方法上一加,后端接口鉴权搞定;前端 v-hasPermi 指令一写,按钮自动显隐。
小团队快速迭代,一周一个版本,客户也满意。那段时间,我逢人就推若依:"哥们,Java 后台就用若依,太省事了。"
蜜月期只维持了一个月。
客户提出了一个听起来很合理的需求:多租户。他们的产品要卖给不同企业,每个企业只能看到自己的数据。
我当时想,这有啥难的?加个 tenant_id 字段,拦截器里注入一下不就行了?
结果一动手,傻了。
若依原生的 RBAC 权限模型根本没有"租户"这个概念。我得自己写拦截器从请求头里取 tenant_id,然后——然后噩梦就开始了。
每一个 MyBatis 的 SQL,每一个查询用户、查询角色、查询字典的地方,我都要手动加上 where tenant_id = ?。改到第30个Mapper的时候,手指已经开始发抖。
这还不算完。像字典表、参数表这种系统级别的配置,理论上不应该隔离——所有租户共用同一套字典。所以我不能一刀切全部加 tenant_id。每个 SQL 前面,我都要想一下:这个表该不该隔离?然后写一堆 if-else 判断。
代码越改越丑,bug 越改越多。
紧接着第二个需求来了:数据权限按行政区划分级。客户说,华北区总监只能看华北的数据,各省经理只能看本省的数据。
若依的数据权限我熟啊,就四种:全部数据权限、本部门、本部门及以下、仅本人。四个选项,没有行政区划这个维度。
我只能在一个叫 DataScope 的注解写完后,在业务代码里手动拼接 SQL:查询条件加上大区、省份、城市的 if-else。这段代码最后膨胀到了 180 多行,每次新加一个数据维度,都要去改这个"SQL 拼接地狱"。
第三个月,来了一个金融客户。
对方的安全评审一上来就问:"你们的登录接口,账号密码是明文传输的?"
我沉默了。
若依的认证授权用的是 Shiro + JWT,登录的时候账号密码确实是明文走 HTTPS。但金融客户不接受,他们要求接口级别的 SM4 加密,而且要有防重放机制——每个请求只能被接受一次,防止被中间人截获后重放攻击。
我搜遍了若依的文档和社区:没有内置的 API 加解密。要么自己集成 SM4,要么换框架。自己集成?考虑到前面两个月踩的坑,我已经没有信心了。
最后一根稻草是分布式幂等。
我们有个支付接口,用户点击"确认支付"按钮,前端做了防重复提交的 loading,但网络抖动的时候,用户刷新页面重新提交了一次——支付接口被调了两次,钱扣了两次。
若依有一个 @RepeatSubmit 防重注解,但它依赖的是 HttpSession。在微服务架构下,Session 不共享,这个注解形同虚设。
客户投诉,公司赔了200块。钱不多,但这件事让我彻底想通了。
还有一件事,平时不想提,但堵在心里很久了:若依的模块结构。
ruoyi-system 模块里,Controller 放在 ruoyi-admin 里,Service 和 Mapper 又在 ruoyi-system 里。想拆成微服务的时候,发现 Controller 和 Service 根本不在同一个模块里——动一个模块,上上下下全要改。
这就像一个装修好的房子,你住着挺舒服,但想改个插座位置,发现墙是承重墙,拆不了。
周末两天没出门,我在 Gitee 上刷了一圈 Java 后台框架。
刷到 Forge Admin 的时候,项目简介里列的功能让我愣住了:
多租户 · 数据权限(含行政区划) · 接口加解密 · 分布式幂等 · AI 代码生成 · 数据大屏
这不就是我过去三个月踩过的每一个坑吗?
再看技术栈:Spring Boot 3.2 + Vue3 + TypeScript,比我当时用的版本新了整整一代。数据库支持 MySQL、PostgreSQL、达梦(国产数据库,金融客户最爱)。
我花了一个周末把核心模块迁移过去。说实话,比想象中顺利得多——因为 Forge Admin 的多租户和数据权限是框架原生支持的,不需要改任何业务代码,只要配置就行了。
多租户:五级忽略策略,200 行拦截器代码直接删了。
Forge Admin 的多租户方案有五个层级的忽略规则:从上下文配置,到全局配置,到手动排除,到自动扫描,再到注解声明。简单说就是——系统表自动跳过不注入 tenant_id,业务表自动注入。之前我自己写的 200 多行拦截器和各种 if-else 判断,全部删掉,一个不留。删代码的感觉,比写代码爽多了。
数据权限:7 大 DataScopeType,行政区划原生支持。
Forge Admin 内置了 7 种数据权限类型:全部、自定义、本部门、本部门及以下、仅本人、本部门及子级自定义、行政区划。而且权限过滤是在 Mapper 层通过 JSqlParser 做 SQL 改写,不是业务代码里手动拼字符串。之前那 180 多行的 if-else SQL 拼接,又删了。
接口安全:RSA 密钥协商 + SM4 加密 + 防重放,金融客户秒过安全审查。
Forge Admin 内置了完整的接口加解密方案:前端发起请求前,先通过 RSA 协商生成会话密钥,后续所有敏感数据用 SM4 或者 AES 加密传输。后端通过 RequestBodyAdvice 自动解密请求体、ResponseBodyAdvice 自动加密响应体,加上时间戳防重放机制。金融客户的安全评审,一次性通过。评审老师看了方案说:"你们这个比我们要求的还严。"
分布式幂等:3 种策略 + SpEL 键生成 + Redisson 锁。
Forge Admin 的幂等方案支持三种策略:严格模式(重复请求直接抛异常)、缓存返回模式(返回首次结果)、令牌模式(先申请令牌再请求)。键的生成支持 SpEL 表达式,锁基于 Redisson 分布式锁。支付接口加上 @Idempotent(key = "#orderNo", strategy = IdempotentStrategy.STRICT),同样的订单号永远只扣一次款。那 200 块,再也不用赔了。
Sa-Token 比 Shiro 轻量太多。
若依用的是 Shiro,说实话 Shiro 这么多年没怎么更新了,排查问题经常要翻源码。Forge Admin 用的 Sa-Token,API 设计更现代,代码量直接少了一半。比如踢人下线,Shiro 要写一堆 Session 操作,Sa-Token 一句 StpUtil.kickout(userId) 完事。
公正地说,若依不是"不好",它只是在某些场景下不够用。
若依的社区是真大。遇到问题,随便一搜,CSDN、掘金、知乎、若依官方文档,答案铺天盖地。新人上手几乎是零门槛——从环境搭建到第一个 CRUD 跑通,跟着文档走,一个小时足矣。
若依的代码生成器对于标准 CRUD 场景非常直接。建表、配置、生成,三步走,不拖泥带水。
而 Forge Admin 的社区目前还比较小。有些问题得自己啃源码,群里的讨论还没那么热。文档在持续完善中,但跟若依全网几万篇教程比起来,还有差距。
这是新框架的代价,但也是早期用户的红利——你遇到的问题,可能就是后续文档的起点。
直接说结论:不后悔换框架,但我后悔没在项目一开始就选对。
如果你只是做单体后台管理系统,标准 CRUD 需求,用户-角色-菜单三板斧打天下——若依完全够用,甚至可以说是最优选择。上手快、社区大、生态成熟,没必要折腾。
但如果你做的是 SaaS 产品,有下面这些需求中的任意两条:
那就别走我踩过的坑了。直接上 Forge Admin。框架没有绝对的好坏,只有场景匹配。若依是一把好锤子,但钉子不是世界上唯一的东西。
你有没有从若依换到其他框架的经历?或者一直用若依遇到了什么难搞的坑?评论区聊聊,说不定你的故事就是下一篇爆款的素材。
Forge Admin 项目地址: