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>

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

相关推荐
牧竹子2 小时前
对原jar包解压后修改原class文件后重新打包为jar
java·jar
尘浮生6 小时前
Java项目实战II基于微信小程序的校运会管理系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
是老余7 小时前
本地可运行,jar包运行错误【解决实例】:通过IDEA的maven package打包多模块项目
java·maven·intellij-idea·jar
crazy_wsp7 小时前
IDEA怎么定位java类所用maven依赖版本及引用位置
java·maven·intellij-idea
bjzhang757 小时前
SpringBoot开发——Maven多模块工程最佳实践及详细示例
spring boot·maven·maven多模块工程
一二小选手9 小时前
【Maven】IDEA创建Maven项目 Maven配置
java·maven
尘浮生10 小时前
Java项目实战II基于微信小程序的电影院买票选座系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
郑祎亦10 小时前
Spring Boot 项目 myblog 整理
spring boot·后端·java-ee·maven·mybatis
Allen Bright17 小时前
maven概述
java·maven
丁总学Java1 天前
Maven项目打包,com.sun.tools.javac.processing
java·maven