若依框架做大了怎么办?多模块 Maven 拆分的完整指南

若依项目做到第三个月,admin 模块越来越臃肿------启动 40 秒、改一行代码全量编译、两个人改同一个文件天天冲突。这篇文章复盘我是怎么把若依从单模块拆成多模块的:哪个先拆、边界怎么画、依赖怎么管、趟过的坑一个不落。


一、单体项目的"三个月魔咒"

最开始搭若依的时候,目录干净得让人舒服。前两周没毛病,改什么都快。

问题从第一个月开始冒头:

症状 具体表现 谁难受
启动变慢 从 8 秒涨到 40 秒 每次调试都等得心烦
编译范围大 改一行 Service,全量 300+ 类重新编译 浪费时间
合并冲突 两个人都在 admin 里加东西,每天 merge 都有冲突 协作成本飙升
边界模糊 CRM 的 Service 和 MES 的 Service 混在一起,越写越不敢删 谁敢重构谁死

到第二个月底,ruoyi-admin 已经塞了 CRM 模块和 MES 模块的全部代码------Controller 40 多个,Service 30 多个,Mapper 50 多个。

单模块不坏,但当你开始纠结"这个类该放哪个包"的时候,就是该拆的时候了。


二、若依框架的模块化设计全景

先看若依官方给的标准模块结构:

perl 复制代码
ruoyi/
├── ruoyi-common/        # 公共工具类、异常、注解、枚举
├── ruoyi-framework/     # 框架核心配置(安全、数据源、Swagger)
├── ruoyi-system/        # 系统管理业务(用户、角色、菜单、部门)
├── ruoyi-generator/     # 代码生成器
├── ruoyi-quartz/        # 定时任务
└── ruoyi-admin/         # 启动模块 + Controller 汇总

依赖链路:只向下,不向上

perl 复制代码
ruoyi-admin  ──→  ruoyi-system  ──→  ruoyi-framework  ──→  ruoyi-common
   (顶层)          (业务层)          (配置层)            (基础层)

没有任何一个底层模块依赖上层模块。 这是 Maven 多模块拆分的第一铁律。


三、实战第一步:把业务模块从 admin 里拆出来

Step 1:创建新模块

pom.xml<modules> 里加一行:

xml 复制代码
<modules>
    <module>ruoyi-common</module>
    <module>ruoyi-framework</module>
    <!-- ... 其他模块 ... -->
    <module>ruoyi-crm</module>        <!-- 新增 -->
</modules>

新建 ruoyi-crm/pom.xml

xml 复制代码
<parent>
    <groupId>com.ruoyi</groupId>
    <artifactId>ruoyi</artifactId>
    <version>3.3.0</version>
</parent>

<artifactId>ruoyi-crm</artifactId>

<dependencies>
    <dependency>
        <groupId>com.ruoyi</groupId>
        <artifactId>ruoyi-common</artifactId>
    </dependency>
    <dependency>
        <groupId>com.ruoyi</groupId>
        <artifactId>ruoyi-system</artifactId>
    </dependency>
</dependencies>

⚠️ 关键:ruoyi-crm 不要依赖 ruoyi-admin。admin 是顶层,业务模块不能反向依赖。

Step 2:迁移代码

bash 复制代码
ruoyi-crm/
├── pom.xml
└── src/main/java/com/ruoyi/crm/
    ├── controller/     ← 从 admin 搬过来
    ├── service/
    ├── service/impl/
    ├── mapper/
    └── domain/

包路径变了:com.ruoyi.web.controller.crmcom.ruoyi.crm.controller,IDE 批量替换即可。

Step 3:admin 加上依赖

xml 复制代码
<!-- ruoyi-admin/pom.xml -->
<dependency>
    <groupId>com.ruoyi</groupId>
    <artifactId>ruoyi-crm</artifactId>
</dependency>

第一个坑:Spring Boot 扫描不到 Bean

代码搬过去,启动报 NoSuchBeanDefinitionException

根因@MapperScan 还在 admin 里指向老路径。

解决 :把 @MapperScan 放到各模块自己内部:

less 复制代码
// ruoyi-crm 模块中
@Configuration
@MapperScan("com.ruoyi.crm.mapper")
public class CrmConfig {
}

四、实战第二步:公共代码怎么不重复

拆完 CRM 和 MES 后,两个模块都需要 ExcelUtil

错误的做法:各 copy 一份。正确做法:抽到 ruoyi-common

bash 复制代码
ruoyi-common/src/main/java/com/ruoyi/common/utils/
├── ExcelUtil.java          # CRM 和 MES 都用
├── PageUtils.java           # 通用分页工具
└── DictUtils.java           # 字典工具

什么时候不该放 common?

CRM 和 MES 之间有一个共享 DTO------CrmCustomerBriefDTO。如果放 common,common 会逐步膨胀成大杂烩。

方案 :建一个 ruoyi-shared-dto 模块,只放跨模块共享的数据对象,common 保持干净。

common 的使命是"基础能力",不是"业务共享"。


五、实战第三步:多模块下的配置管理

每个模块不能各配各的。 Spring Boot 启动时只加载一次 application.yml,位置在 admin 的 resources 里。

模块专属配置用 @ConfigurationProperties + 前缀隔离:

less 复制代码
// ruoyi-crm 模块中
@Data
@Component
@ConfigurationProperties(prefix = "crm")
public class CrmConfig {
    private int importMaxRows = 5000;
    private int opportunityExpireDays = 30;
}
arduino 复制代码
# application.yml(只在 admin 中维护)
crm:
  import-max-rows: 5000
  opportunity-expire-days: 30

所有 yml 文件都放 ruoyi-admin/src/main/resources/,业务模块只定义 @ConfigurationProperties 类。


六、Maven 多模块构建与打包

版本号统一

xml 复制代码
<!-- 根 pom.xml -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-common</artifactId>
            <version>${ruoyi.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

子模块引用不写版本号,由根 pom 统一管控。

第二个大坑:循环依赖

CRM 依赖 MES、MES 又依赖 CRM → Circular dependency

解法:提取接口到 common,依赖接口而非依赖实现:

kotlin 复制代码
// ruoyi-common 中定义接口
public interface CustomerBriefService {
    CustomerBriefDTO getBrief(Long customerId);
}

// ruoyi-crm 中实现接口
@Service
public class CustomerBriefServiceImpl implements CustomerBriefService { ... }

// ruoyi-mes 中依赖接口,不依赖模块本身
@Service
public class QualityCheckService {
    @Autowired
    private CustomerBriefService customerBriefService;  // 注入接口
}

MES 只依赖 common 中的接口,不依赖 CRM 模块------循环依赖解了。


七、拆分后的收益

维度 拆之前 拆之后
启动时间 ~40 秒 ~18 秒
编译时间 改一行全量 300+ 类 只编译当前模块
代码冲突 天天 merge 冲突 基本不冲突
新人上手 要弄懂整个 admin 读懂一个模块就能开工
删除成本 不敢删 Maven 依赖图一眼看穿,敢删

八、总结

三条核心原则回顾:

① 依赖只向下。 底层模块永远不依赖上层。

② 公共代码提 common,业务代码放模块。 common 是基础能力集,不是垃圾桶。

③ 一次只拆一个模块。 拆一个,跑通,再拆下一个。

什么时候该拆?

  • 启动时间超过 30 秒?
  • 两个人以上在同一个模块里写代码?
  • 你开始纠结"这个类到底该放哪个包"?

两个满足了就动手。拆分是为协作和长期维护服务的,不要为了拆而拆。


关于作者

我是一名全栈开发者,目前在深圳创业,专注于印刷包装行业的数字化系统建设。

技术栈:Java / Spring Boot / Vue3 / uni-app / MySQL / Redis

我会持续分享全栈开发实战、若依框架深度教程、MES & CRM 产品设计思路。若依框架实战系列还有:

每周更新,欢迎关注微信公众号「MqCode」,第一时间获取全栈开发实战内容 👇

相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
胡写代码2 天前
别再前后端各写一套表单校验了
java·后端
大勇前进2 天前
原生 PHP 还是 Laravel?小项目到底要不要上框架
后端
yuzhi_liu2 天前
我用 LangGraph4j 实现 Multi-Agent Supervisor
后端
alsmile2 天前
Node-RED 之外,国产规则引擎的新方案:基于标准语法,Go 先行实现
后端·开源·go
大白802 天前
PHP 内存溢出排查思路:看懂报错日志,精准定位问题
后端
二月龙2 天前
PHP 接口返回统一响应封装,让前后端对接更省心
后端
盖伦发发2 天前
软件工程SOLID 五大设计原则
后端·软件工程