
本文详解 Maven 中 maven-shade-plugin 未生效的根本原因:插件被错误置于 块内,导致其不参与构建生命周期;提供精简、可靠、经验证的配置方案,并说明验证方法与关键注意事项。
本文详解 maven 中 `maven-shade-plugin` 未生效的根本原因:插件被错误置于 `
在 Maven 构建中,生成一个包含全部依赖(含 gnu.getopt 等第三方库)且可直接通过 java -jar 运行的 Fat Jar(又称 Uber JAR),maven-shade-plugin 是最推荐的官方方案——它不仅支持依赖打包,还提供类重定位(relocation)、资源合并、MANIFEST 自动注入等高级能力。但实践中,绝大多数“配置无效”问题并非源于插件本身,而是 Maven 配置作用域的误解。
❌ 常见错误:误用
你提供的 pom.xml 中,maven-shade-plugin 被包裹在
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<!-- ... -->
</plugin>
</plugins>
</pluginManagement>
</build>⚠️ 关键事实:
仅用于集中声明插件的默认版本和配置模板,不会触发任何执行; - 它不绑定生命周期(如 package 阶段),也不参与实际构建流程;
- 此时 Maven 仍会调用默认的 maven-jar-plugin(日志中可见 maven-jar-plugin:2.4:jar (default-jar)),生成仅含自身字节码的普通 JAR —— 这正是你看到 jar tf 输出中无 gnu/getopt/ 类、且 java -jar 报错 no main manifest attribute 的根本原因。
✅ 正确配置:移至 (项目级启用)
将
<build>
<finalName>hello-fat-jar</finalName> <!-- 可选:自定义输出文件名 -->
<plugins>
<!-- ✅ 正确位置:激活插件并绑定到生命周期 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version> <!-- 推荐使用 3.4.1+(兼容 JDK 17+) -->
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<!-- 指定启动主类,写入 MANIFEST.MF -->
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.example.Hello</mainClass>
</transformer>
</transformers>
<!-- 可选:避免生成 dependency-reduced-pom.xml(简化输出) -->
<createDependencyReducedPom>false</createDependencyReducedPom>
<!-- 可选:禁用 shaded artifact 附加(避免生成两个 jar) -->
<shadedArtifactAttached>false</shadedArtifactAttached>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>? 提示:
可省略,默认为 ${artifactId}-${version};若需同时保留原始 jar 与 fat jar,可设 true (此时 fat jar 名为 xxx-shaded.jar)。
? 验证是否生效
执行构建并检查关键信号:
mvn clean package -X | grep -i "shade"
✅ 成功日志应包含:
[DEBUG] Configuring mojo 'org.apache.maven.plugins:maven-shade-plugin:3.4.1:shade' ... [INFO] --- maven-shade-plugin:3.4.1:shade (default) @ hello-fat-jar --- [INFO] Including gnu.getopt:java-getopt:jar:1.0.13 in the shaded jar.
✅ 检查输出文件:
ls target/ # 应出现:hello-fat-jar-0.1-SNAPSHOT.jar(即 fat jar,体积显著大于原 jar) jar -tf target/hello-fat-jar-0.1-SNAPSHOT.jar | head -20 # 应包含:gnu/getopt/Getopt.class、META-INF/MANIFEST.MF 等 # 查看 MANIFEST 是否含 Main-Class unzip -p target/hello-fat-jar-0.1-SNAPSHOT.jar META-INF/MANIFEST.MF # 输出应含:Main-Class: org.example.Hello
✅ 最终运行验证:
java -jar target/hello-fat-jar-0.1-SNAPSHOT.jar -x # 输出:Hello X! \n Goodbye
⚠️ 注意事项与最佳实践
- 版本兼容性:JDK 17+ 项目请使用 maven-shade-plugin ≥ 3.4.1(旧版如 2.4.3 对模块化支持不佳);
- 依赖冲突处理:若多个依赖含同名资源(如 META-INF/services/*),需添加 ServicesResourceTransformer 避免覆盖;
-
类重定位(Re-location):当需规避依赖间类名冲突(如嵌入不同版本的 Guava),使用
配置将包路径重命名; - 与 maven-assembly-plugin 对比:Shade 更适合生产环境——它原生支持资源合并策略与类隔离,而 Assembly 更侧重灵活归档格式(如 tar.gz);
-
多模块项目:确保 Shade 插件配置在具体子模块的 pom.xml 中(如 simple-server/pom.xml),而非父 POM 的
。
至此,你已掌握构建可执行 Fat Jar 的核心要点:配置位置决定执行权,

















