如何通过Maven Shade插件生成指定依赖与第三方依赖两类Fat Jar?
解决方案:用Maven Shade插件生成拆分的Fat Jar
当然可以实现!我之前在项目里遇到过类似需求,核心是通过配置两个独立的Shade插件执行实例,分别控制不同的依赖包含规则,从而生成两个目标Jar包。下面是具体的实现步骤和配置示例:
核心思路
Shade插件的默认行为是包含项目自身代码+所有依赖,但我们可以通过artifactSet的includes/excludes规则精准控制依赖范围,再通过多个execution实例分别处理两种打包需求。
具体POM配置示例
在你的pom.xml的<build><plugins>节点下添加两个Shade插件的execution配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.4.1</version> <executions> <!-- 第一个execution:生成包含自有代码 + com.acme依赖的Jar --> <execution> <id>shade-with-acme</id> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <!-- 自定义输出Jar名称,避免覆盖默认Jar --> <finalName>${project.build.finalName}-with-acme</finalName> <artifactSet> <!-- 只包含com.acme下的所有依赖 --> <includes> <include>com.acme:*</include> </includes> </artifactSet> <!-- 项目自身的编译代码会默认被包含,无需额外配置 --> </configuration> </execution> <!-- 第二个execution:生成仅包含第三方依赖(排除自有代码和com.acme)的Jar --> <execution> <id>shade-third-party</id> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <finalName>${project.build.finalName}-third-party</finalName> <artifactSet> <!-- 排除自有项目代码和com.acme依赖 --> <excludes> <exclude>${project.groupId}:${project.artifactId}</exclude> <exclude>com.acme:*</exclude> </excludes> </artifactSet> <!-- 关闭默认的项目代码打包,只保留依赖 --> <shadeSourcesContent>false</shadeSourcesContent> </configuration> </execution> </executions> </plugin>
配置说明
- 第一个execution:绑定到
package阶段,只包含com.acme:*的依赖,项目自身的编译类会默认被Shade插件打包进去,最终生成如your-app-with-acme.jar的文件。 - 第二个execution:同样绑定到
package阶段,通过excludes排除自有项目和com.acme的依赖,同时设置shadeSourcesContent=false关闭项目代码打包,最终生成仅含第三方依赖的your-app-third-party.jar。
替代方案:用Maven Profiles拆分执行
如果不需要同时生成两个Jar,可以把两个Shade配置放到不同的Profile中,通过命令行参数触发:
<profiles> <profile> <id>build-with-acme</id> <build> <plugins> <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> <finalName>${project.build.finalName}-with-acme</finalName> <artifactSet> <includes> <include>com.acme:*</include> </includes> </artifactSet> </configuration> </execution> </executions> </plugin> </plugins> </build> </profile> <profile> <id>build-third-party</id> <build> <plugins> <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> <finalName>${project.build.finalName}-third-party</finalName> <artifactSet> <excludes> <exclude>${project.groupId}:${project.artifactId}</exclude> <exclude>com.acme:*</exclude> </excludes> </artifactSet> <shadeSourcesContent>false</shadeSourcesContent> </configuration> </execution> </executions> </plugin> </plugins> </build> </profile> </profiles>
执行时用:
# 生成自有代码+com.acme依赖的Jar mvn package -P build-with-acme # 生成第三方依赖的Jar mvn package -P build-third-party
关键注意事项
- 确保两个execution的
id唯一,避免Maven执行冲突。 - 自定义
finalName是必须的,否则两个Jar会互相覆盖。 shadeSourcesContent=false是第二个execution的关键,它会阻止Shade打包项目自身的代码,只保留依赖。
内容的提问来源于stack exchange,提问作者ktdrv




