多模块Spring Boot项目独立模块合并至Uber JAR并按需启动指定模块的技术咨询
我来给你分享一个亲测可行的方案,完美解决你把多个独立Spring Boot模块合并成单一Fat Jar,还能通过参数指定运行对应模块的需求,分几个关键步骤来实现:
1. 模块D的Maven配置(核心用Shade插件)
要把A、B、C三个模块的所有类和资源都合并到D的Jar里,Maven Shade插件是最佳选择。你需要在模块D的pom.xml里配置如下:
<build> <plugins> <!-- 可选:Spring Boot插件,用来处理可执行Jar的结构 --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> <configuration> <!-- 指定模块D的启动类作为统一入口 --> <mainClass>com.example.d.DApplication</mainClass> </configuration> </execution> </executions> </plugin> <!-- Shade插件:负责合并所有依赖模块的类和资源 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.4.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> <transformers> <!-- 保留Spring Boot可执行Jar的必要结构 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> <transformer implementation="org.springframework.boot.maven.PropertiesMergingResourceTransformer"> <resource>META-INF/spring.factories</resource> </transformer> <transformer implementation="org.springframework.boot.maven.ShadeResourceTransformer"> <mainClass>com.example.d.DApplication</mainClass> </transformer> <!-- 合并Spring相关的配置文件,避免覆盖 --> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.handlers</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.schemas</resource> </transformer> </transformers> <!-- 确保模块D里的config目录下的配置文件全部被打包 --> <resourceTransformers> <resourceTransformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer"> <includes> <include>config/**</include> </includes> </resourceTransformer> </resourceTransformers> </configuration> </execution> </executions> </plugin> </plugins> </build>
⚠️ 注意:如果A、B、C模块自己的pom.xml里配置了Spring Boot插件的repackage目标,记得把它们改成<skip>true</skip>,因为我们只需要模块D生成可执行Jar,其他模块作为普通依赖Jar即可。
2. 调整模块D的启动类
模块D需要一个统一的启动入口,确保能扫描到所有模块的组件。假设A、B、C的包分别是com.example.a、com.example.b、com.example.c,模块D的包是com.example.d,启动类可以这么写:
package com.example.d; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; @SpringBootApplication // 扫描所有模块的包路径,保证各个模块的Bean能被加载 @ComponentScan(basePackages = {"com.example.a", "com.example.b", "com.example.c", "com.example.d"}) public class DApplication { public static void main(String[] args) { SpringApplication.run(DApplication.class, args); } }
3. 确认配置文件结构
确保模块D的src/main/resources目录下的结构和你规划的一致:
src/main/resources/ ├── config/ │ ├── A/ │ │ └── application-A.properties │ ├── B/ │ │ └── application-B.properties │ └── C/ │ └── application-C.properties └── application.properties(可选,放所有模块共享的公共配置)
打包后,这些文件会被放在Fat Jar的classpath:/config/目录下,完全符合你需要的路径。
4. 运行验证
执行mvn clean package后,模块D的target目录下会生成可执行Jar(比如D-shade-test.jar),然后就可以用你想要的命令运行对应模块:
- 运行模块A:
java -jar D-shade-test.jar --spring.config.location=classpath:/config/A/application-A.properties
- 运行模块B:
java -jar D-shade-test.jar --spring.config.location=classpath:/config/B/application-B.properties
如果你想更简洁,还可以结合Spring的Profile功能:把每个模块的配置文件直接放在src/main/resources下,命名为application-A.properties,运行时只需要指定--spring.profiles.active=A,Spring会自动加载对应的配置文件,不过这需要调整配置文件的路径,看你更习惯哪种方式。
5. 额外的灵活方案(适合模块独立性强的场景)
如果每个模块都有自己的@SpringBootApplication启动类,你甚至可以不用模块D的启动类,运行时直接指定对应模块的启动类即可:
# 运行模块A,指定A的启动类和配置文件 java -jar D-shade-test.jar -Dspring.main.class=com.example.a.AApplication --spring.config.location=classpath:/config/A/application-A.properties
这种方式不需要修改模块D的启动类,对原有模块的侵入性更小。
避坑提醒
- 资源冲突:如果A、B、C模块有同名的资源文件(比如
logback.xml),Shade插件默认会覆盖,这时候要通过AppendingTransformer或者IncludeResourceTransformer来处理,确保必要的资源被保留或合并。 - 依赖版本冲突:如果三个模块依赖不同版本的第三方库,一定要在模块D的
pom.xml里统一版本,避免Jar Hell问题。
内容的提问来源于stack exchange,提问作者Suresh Kumar

