maven-shade-plugin - 解决 Jar 包冲突新思路

打包是一个比较头疼的事情,默认 Maven 打包的结果只包含项目本身的代码,如果要执行代码,还得带上依赖。maven-shade-plugin插件就能够帮我们把项目依赖的包也打进最终文件。


文章目录


1、Maven 项目中三方依赖冲突的问题

在现代 Java 开发中,Maven 项目打包是一个比较头疼的事情,我们经常需要处理项目的依赖管理和打包问题。

在 Maven 项目中引入第三方组件时,这些三方组件的依赖可能与项目已有的依赖发生冲突。例如,如果第三方组件依赖的 HttpClient 版本是 4.5.x,而项目中已有的 HttpClient 版本是 3.1.x,就会产生以下两种情况:

  1. 用高版本覆盖低版本:如果使用第三方组件的高版本 HttpClient 覆盖项目中的低版本 HttpClient,有可能导致项目启动或运行失败。即使高版本兼容低版本,这种高风险的操作也是不被允许的;

  2. 排除高版本依赖:如果在第三方 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>

通过这种方式,可以进一步控制打包过程中的细节,满足不同的需求。

相关推荐
smile-yan1 小时前
Provides transitive vulnerable dependency maven 提示依赖存在漏洞问题的解决方法
java·maven
果冻的猿宇宙1 小时前
Maven 中央仓库访问过慢的解决方案--设置国内镜像
maven·镜像·仓库·aliyun·国内镜像·mirror
哆啦 AI 梦1 小时前
【Maven】如何解决Maven循环依赖?
maven·循环依赖
Earnest~1 小时前
Maven极简安装&配置-241223
java·maven
皮蛋很白1 小时前
Maven 环境变量 MAVEN_HOME 和 M2_HOME 区别以及 IDEA 修改 Maven repository 路径全局
java·maven·intellij-idea
w_312345413 小时前
自定义一个maven骨架 | 最佳实践
java·maven·intellij-idea
张国荣家的弟弟13 小时前
【Yonghong 企业日常问题 06】上传的文件不在白名单,修改allow.jar.digest属性添加允许上传的文件SH256值?
java·jar·bi
哆啦 AI 梦19 小时前
【Maven】Maven的classpath
maven·classpath
CodeChampion19 小时前
61.基于SpringBoot + Vue实现的前后端分离-在线动漫信息平台(项目+论文)
java·vue.js·spring boot·后端·node.js·maven·idea
新手小袁_J1 天前
JDK11下载安装和配置超详细过程
java·spring cloud·jdk·maven·mybatis·jdk11