多模块Maven项目构建后的依赖管理方案及相关问题咨询
关于你提到的重复打包问题
你顾虑的情况确实存在:如果给每个子模块单独配置maven-shade-plugin执行打包,不管是父POM通过dependencyManagement统管的公共第三方依赖(比如JUnit、common-lang这类通用组件),还是你项目内部互相依赖的子模块,只要被多个需要打包的子模块引用,就会被重复复制进对应子模块的最终JAR产物里。
该方案的合理性判断
这个做法有没有问题完全取决于你的业务场景:
- 如果各子模块最终是独立进程运行的程序/微服务,互相不在同一个JVM环境下加载,那重复打包本质上不会产生功能问题,仅会多占用一点磁盘存储,在模块数量不多的情况下完全可以接受,额外的存储成本几乎可以忽略。你唯一需要做的优化是在shade配置里排除
scope=test的依赖(比如JUnit),避免测试用的依赖被打入生产环境的包。 - 如果所有子模块最终要放到同一个JVM进程下运行,或者你的项目模块数量极多、CI/CD存储成本很高,那重复打包的冗余就属于需要优化的问题。
多模块项目推荐的构建方案
根据不同场景可以选择更适配的方案:
- 单入口统一运行场景
如果所有模块最终合并成一个可执行程序,不需要给每个子模块单独打可执行包,只需要单独建一个统一的启动模块,依赖所有需要用到的业务子模块,仅在这个启动模块里配置一次maven-shade-plugin即可,所有公共依赖只会被打包一次,完全没有冗余。 - 多独立程序场景
如果每个子模块都是独立运行的服务,优先根据技术栈选适配的打包插件:
- Spring栈项目直接用
spring-boot-maven-plugin,默认就会打可执行fat jar,也支持自定义排除不需要的依赖 - 非Spring的普通Java项目,可以用
maven-assembly-plugin自定义打包规则,灵活控制要打进包的内容
- 极致减小编译产物体积场景
如果需要彻底避免依赖重复占用空间,可以用瘦包构建方案:
通过maven-dependency-plugin将所有公共第三方依赖统一拷贝到外部的lib目录,再通过maven-jar-plugin配置所有子模块JAR的Manifest属性,指定依赖加载路径为公共的lib目录,运行时通过java -cp lib/* -jar 你的模块包.jar的方式启动即可,所有模块共用同一份依赖副本,完全没有冗余。
补充说明:父POM的
dependencyManagement仅用于统一管控所有子模块的依赖版本,不会影响打包阶段的依赖复制逻辑,因此也无法避免重复打包的问题。
内容的提问来源于stack exchange,提问作者thorald_
相关产品推荐
相关产品推荐

