maven打包包含第三方依赖
Maven 打包包含第三方依赖:Assembly 与 Shade 插件详解
在 Java 项目部署时,常常需要将第三方依赖一并打包,生成可直接运行的 Jar 包(无需用户手动下载依赖)。Maven 提供了 maven-assembly-plugin 和 maven-shade-plugin 两个核心插件实现这一需求,本文将详细介绍两者的配置与差异。
为什么需要包含第三方依赖?
- 独立运行:生成的 Jar 包可直接通过
java -jar命令运行,无需依赖外部 Maven 仓库。 - 环境一致性:避免因依赖版本差异导致的 “本地能跑,线上报错” 问题。
- 简化部署:只需传输一个 Jar 包,无需额外配置依赖路径。
Assembly 插件:灵活的打包方案
maven-assembly-plugin 是 Maven 官方插件,支持多种打包格式(如 Jar、Zip、Tar),并可通过描述符(descriptor)自定义打包内容。
核心配置(包含所有依赖的 Jar 包)
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version> <!-- 推荐使用最新版本 -->
<configuration>
<!--
描述符
1、bin - 将jar包打zip包
2、jar-with-denpendencies - 带有依赖的jar包
3、project - 将工程源代码打包
4、src - 将工程src目录下的源代码打包
-->
<!-- 描述符:指定打包类型,jar-with-dependencies 表示包含所有依赖 -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- 配置可执行 Jar 的入口类(可选) -->
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.zhanghe.Main</mainClass> <!-- 替换为你的主类全路径 -->
</manifest>
</archive>
</configuration>
<!-- 绑定到 package 阶段,执行 mvn package 时自动打包 -->
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal> <!-- 单一次打包 -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
执行与效果
- 执行命令:
mvn clean package - 生成的 Jar 包位于
target/目录,命名格式为[artifactId]-[version]-jar-with-dependencies.jar(如demo-1.0-SNAPSHOT-jar-with-dependencies.jar)。 - 包内结构:包含项目自身的类和所有第三方依赖的类(平铺在
BOOT-INF/classes或根目录下)。
其他常用描述符
除了 jar-with-dependencies,Assembly 插件还支持多种预设描述符:
| 描述符 | 作用 |
|---|---|
bin |
打包成 Zip 格式,包含 Jar 包和脚本 |
project |
打包项目源码和资源(用于分发源码) |
src |
仅打包 src 目录下的源代码 |
如需自定义打包规则(如排除某些依赖、添加配置文件),可创建自定义描述符文件(如 src/main/assembly/assembly.xml),并在 <configuration> 中指定:
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
Shade 插件:解决依赖冲突的高级方案
maven-shade-plugin 是 Apache 提供的另一个打包插件,相比 Assembly 插件,它支持依赖重命名和冲突解决,适合复杂项目。
基础配置(包含依赖并可执行)
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version> <!-- 推荐最新版本 -->
<executions>
<execution>
<phase>package</phase> <!-- 绑定到 package 阶段 -->
<goals>
<goal>shade</goal>
</goals>
<configuration>
<!-- 配置可执行入口类 -->
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.zhanghe.Main</mainClass> <!-- 主类全路径 -->
</transformer>
</transformers>
<!-- 可选:重命名输出 Jar 包(默认覆盖原 Jar) -->
<finalName>${project.artifactId}-${project.version}-shaded</finalName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
执行与效果
- 执行命令:
mvn clean package - 生成的 Jar 包位于
target/目录,默认覆盖原 Jar 包(或按finalName命名,如demo-1.0-SNAPSHOT-shaded.jar)。 - 包内结构:依赖类会被合并到 Jar 中,支持通过配置排除或重命名类。
高级功能:解决依赖冲突
当多个依赖包含同名类时,Shade 插件可通过 Relocation 重命名包路径,避免冲突:
<configuration>
<relocations>
<!-- 将 com.google.gson 重命名为 shaded.com.google.gson -->
<relocation>
<pattern>com.google.gson</pattern>
<shadedPattern>shaded.com.google.gson</shadedPattern>
</relocation>
</relocations>
</configuration>
此外,还可排除不需要的依赖:
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude> <!-- 排除签名文件 -->
<exclude>META-INF/*.DSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
Assembly 与 Shade 插件的对比
| 特性 | Assembly 插件 | Shade 插件 |
|---|---|---|
| 依赖处理 | 简单合并,不处理同名类冲突 | 支持重命名类、排除冲突依赖 |
| 可执行 Jar | 支持(需配置 manifest) | 支持(通过 transformer 配置) |
| 打包格式 | 支持 Jar、Zip、Tar 等多种格式 | 主要生成 Jar 格式 |
| 适用场景 | 简单项目,需包含所有依赖 | 复杂项目,存在依赖冲突或需定制化打包 |
| 输出 Jar 大小 | 较大(包含所有依赖,可能有冗余) | 可通过过滤减小体积 |
使用建议
- 简单项目:优先选择
assembly插件,配置简单,满足基本需求。 - 复杂项目:使用
shade插件,解决依赖冲突,增强打包灵活性。 - 可执行 Jar:两者均需配置
mainClass,确保能通过java -jar直接运行。 - 版本控制:始终指定插件的具体版本(如
3.3.0),避免因版本差异导致的问题。