打包是一个比较头疼的事情,默认 Maven 打包的结果只包含项目本身的代码,如果要执行代码,还得带上依赖。maven-shade-plugin插件就能够帮我们把项目依赖的包也打进最终文件。
文章目录
-
-
- [1、Maven 项目中三方依赖冲突的问题](#1、Maven 项目中三方依赖冲突的问题)
- 2、maven-shade-plugin介绍
- [3、使用 maven-shade-plugin 解决 Jar 包冲突示例](#3、使用 maven-shade-plugin 解决 Jar 包冲突示例)
- 4、注意事项
- 5、其他功能
-
1、Maven 项目中三方依赖冲突的问题
在现代 Java 开发中,Maven 项目打包是一个比较头疼的事情,我们经常需要处理项目的依赖管理和打包问题。
在 Maven 项目中引入第三方组件时,这些三方组件的依赖可能与项目已有的依赖发生冲突。例如,如果第三方组件依赖的 HttpClient 版本是 4.5.x,而项目中已有的 HttpClient 版本是 3.1.x,就会产生以下两种情况:
-
用高版本覆盖低版本:如果使用第三方组件的高版本 HttpClient 覆盖项目中的低版本 HttpClient,有可能导致项目启动或运行失败。即使高版本兼容低版本,这种高风险的操作也是不被允许的;
-
排除高版本依赖:如果在第三方 Maven 依赖中排除了高版本的 HttpClient,使其使用项目中的低版本 HttpClient,可能会因为版本不一致导致第三方组件无法正常使用。
在这样的情况下,我们如何保证在不影响项目原有依赖版本的前提下,正常使用第三方组件呢?这时可以考虑使用 Maven-Shade-Plugin 插件。这个插件可以将第三方组件及其依赖打包并重命名包名,以避免冲突,从而确保项目的稳定运行。
2、maven-shade-plugin介绍
maven-shade-plugin 是 Maven 官方网站中提供的一个插件,官方文档中定义其功能如下:
This plugin provides the capability to package the artifact in an uber-jar, including its dependencies and to shade - i.e. rename - the packages of some of the dependencies.
简单来说就是将依赖的包在 Package 阶段一起打入 Jar 包中,以及对依赖的 Jar 包进行重命名从而达到隔离的作用。这里为了解决上面的问题我们主要使用第二个功能特性,使得相同依赖不同版本达到共存的目的。
3、使用 maven-shade-plugin 解决 Jar 包冲突示例
3.1、环境准备
这里以 fastjson 库为例,模拟使用 maven-shade-pluginn 解决项目中不同版本共存的问题。假设原项目使用的是 1.1.15 版本的 fastjson:
xml
<!-- 原项目依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.15</version>
</dependency>
并引入一个第三方依赖,该依赖使用 1.2.75 版本的 fastjson:
xml
<!-- 第三方依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
3.2、解决方案
搭建一个新的模块 rename-dependencies
,专门用于存放 1.2.75 版本的 fastjson 依赖。在 pom.xml
文件中添加该依赖,并配置 maven-shade-plugin:
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<groupId>com.example</groupId>
<artifactId>rename-dependencies</artifactId>
<version>1.0-SNAPSHOT</version>
<modelVersion>4.0.0</modelVersion>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<relocations>
<relocation>
<pattern>com.alibaba</pattern>
<shadedPattern>shade.com.alibaba</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
配置文件中的 relocations
部分通过重命名包名来隔离依赖。在这个例子中,将以 com.alibaba
开头的包名重命名为 shade.com.alibaba
。
3.3、引入重命名后的依赖
将 rename-dependencies
模块打包后,在原项目中引入:
xml
<dependency>
<groupId>com.example</groupId>
<artifactId>rename-dependencies</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
引入后,项目中的 fastjson
包名将会被重命名,确保不同版本可以共存。
4、注意事项
在实际操作中,可能会遇到引入依赖后找不到重命名的包的问题。此时,可以通过以下方法解决:
- 将重命名模块从项目 Maven 中移除,然后重新引入。
- 新建一个独立项目专门用于依赖重命名。
5、其他功能
除了包重命名外,maven-shade-plugin 还支持打入和排除指定的 JAR 包及资源文件。例如:
xml
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
通过这种方式,可以进一步控制打包过程中的细节,满足不同的需求。