Maven Shade Plugin 使用详细说明

Maven Shade Plugin 使用详细说明

maven-shade-plugin 是一个 Maven 插件,用于将项目及其所有依赖项打包成一个可执行的胖 JAR(fat JAR)。这个插件不仅可以合并多个依赖,还支持过滤、排除、修改 MANIFEST 文件等高级功能。本文将深入介绍 maven-shade-plugin 的使用方法和配置技巧。

一、什么是 maven-shade-plugin

maven-shade-plugin 是 Apache Maven 提供的一个插件,用于将项目的所有依赖项打包成一个可执行的胖 JAR 文件。这种 JAR 包包含所有项目所需的依赖项,可以在不额外配置的情况下直接运行。在构建微服务、发布可执行应用时,使用胖 JAR 可以减少部署复杂度。

二、maven-shade-plugin 的基本用法
  1. 引入插件

    在项目的 pom.xml 文件中引入 maven-shade-plugin,并在 package 阶段执行:

    xml 复制代码
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.4.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
  2. 指定 Main Class

    configuration 节点中设置主类,使生成的 JAR 文件可以直接通过 java -jar 命令运行:

    xml 复制代码
    <configuration>
        <transformers>
            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                <mainClass>com.example.MainClass</mainClass>
            </transformer>
        </transformers>
    </configuration>
三、排除签名文件防止"Invalid signature file digest for Manifest main attributes"错误

在运行胖 JAR 文件时,可能会遇到 Invalid signature file digest for Manifest main attributes 错误。这通常是因为 JAR 包中的 META-INF/*.SFMETA-INF/*.DSAMETA-INF/*.RSA 等签名文件导致的。为了解决这个问题,可以使用 maven-shade-plugin 排除这些文件:

xml 复制代码
<configuration>
    <filters>
        <filter>
            <artifact>*:*</artifact>
            <excludes>
                <exclude>META-INF/*.SF</exclude>
                <exclude>META-INF/*.DSA</exclude>
                <exclude>META-INF/*.RSA</exclude>
            </excludes>
        </filter>
    </filters>
</configuration>

这段配置可以过滤所有签名文件,避免出现"Invalid signature file digest for Manifest main attributes"错误。

四、处理依赖冲突与资源合并

在合并依赖项时,可能会出现资源冲突,比如多个依赖包含同样的资源文件。这时可以使用 transformers 来解决冲突。

  1. 合并特定资源文件

    使用 AppendingTransformer 可以合并特定的资源文件,如 META-INF/spring.factories

    xml 复制代码
    <transformers>
        <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
            <resource>META-INF/spring.factories</resource>
        </transformer>
        <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
            <mainClass>com.example.MainClass</mainClass>
        </transformer>
    </transformers>
  2. 重命名包路径避免类冲突

    使用 relocations 可以将某些包路径重命名,以防止不同依赖中的类冲突:

    xml 复制代码
    <relocations>
        <relocation>
            <pattern>com.example.some.library</pattern>
            <shadedPattern>com.example.shaded.some.library</shadedPattern>
        </relocation>
    </relocations>
五、完整配置示例

以下是一个整合了过滤、合并和重命名的 maven-shade-plugin 配置示例:

xml 复制代码
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.4.1</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>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>META-INF/spring.factories</resource>
                            </transformer>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>com.example.MainClass</mainClass>
                            </transformer>
                        </transformers>
                        <relocations>
                            <relocation>
                                <pattern>com.example.some.library</pattern>
                                <shadedPattern>com.example.shaded.some.library</shadedPattern>
                            </relocation>
                        </relocations>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

此配置确保生成的胖 JAR 文件没有签名文件,能够直接运行且不受类冲突影响。

六、注意事项

在使用 maven-shade-plugin 时,有几个关键点需要注意,以确保打包过程顺利并获得预期效果。以下将详细阐述使用胖 JAR 文件可能遇到的问题及其解决方法:

1. 胖 JAR 文件体积较大

打包成胖 JAR 文件的主要特点是它将所有依赖项整合到一个单一的 JAR 文件中。这在部署和分发时确实便捷,但也带来了一些潜在问题:

  • 存储空间:胖 JAR 包含所有依赖项,体积会大幅增加。对于资源受限的环境(例如嵌入式设备或低带宽场景),胖 JAR 可能会占用过多的磁盘空间和传输资源。这种情况下,可以考虑将一些公共依赖项单独发布,以减少胖 JAR 的体积。
  • 内存使用:加载胖 JAR 时,JVM 会将整个文件载入内存。若项目依赖众多且规模庞大,会导致启动时占用较多内存。对此,可以通过优化依赖和精简项目来缓解。
  • 不适合大型项目:当项目中有大量依赖项或 JAR 文件时,胖 JAR 的体积可能会非常庞大,这会影响构建和传输速度。因此,在大型项目中,可以使用轻量级打包方式(例如 Spring Boot 提供的依赖分层打包)来替代胖 JAR。
2. 构建时间增加

maven-shade-plugin 在打包过程中会将项目及其所有依赖项合并成一个胖 JAR 文件,这一过程通常会消耗较多时间:

  • 打包性能问题 :打包过程中的每一步(如签名文件过滤、资源合并和包路径重命名)都可能导致构建时间延长。特别是在项目依赖项较多时,构建时间可能会显著增加。可以使用 mvn package -DskipTests 命令跳过测试步骤以加快打包速度。
  • 构建过程调优:为减少打包时间,可尝试减少无关紧要的依赖项,或使用缓存功能(如 Maven 的本地仓库缓存),尽量减少对网络依赖的重新下载。
  • 增量构建:如果项目频繁构建,考虑使用增量构建工具或分层构建策略,确保每次只构建修改过的部分,从而减少整体构建时间。
3. 资源冲突和合并问题

在胖 JAR 文件中,不同的依赖可能包含相同的资源文件(如配置文件、属性文件等),这会导致资源冲突。使用 maven-shade-plugin 时,必须配置合理的 transformers 来处理资源冲突问题:

  • 常见冲突资源 :某些配置文件,如 META-INF/spring.factoriesMETA-INF/services/* 或日志配置文件(如 logback.xml),经常会在依赖项中重复出现,导致冲突。为避免问题,可以使用 AppendingTransformer 合并此类文件。
  • 冲突排查与定位:当胖 JAR 出现无法正常运行的情况(如类加载异常或配置未生效),检查 JAR 内部资源冲突通常是解决问题的关键。可以使用工具(如 jar-utility)解压胖 JAR 并手动检查冲突资源。
  • 适当过滤与合并 :使用过滤器(filters)排除不必要的资源文件,可以有效减少资源冲突。对于必须合并的资源文件,确保配置正确的 transformers 类型。需要注意的是,一些依赖可能包含必需的配置文件,排除或合并不当会导致程序运行异常。
4. 运行时依赖的外部资源

胖 JAR 文件虽然封装了大部分依赖项,但仍有一些资源或配置文件可能需要外部访问:

  • 外部配置文件 :尽管胖 JAR 自带配置文件,但在某些场景下,使用外部配置文件(例如 Spring Boot 的外部化配置)可以提高灵活性。通过在 java -jar 命令中指定 --spring.config.location 参数,可以加载外部配置。
  • 依赖于外部资源的库:一些依赖库需要额外的文件或服务支持(如数据库驱动程序或证书文件),这些资源可能无法封装到胖 JAR 中。确保此类资源在部署环境中可用,以避免运行时异常。
5. 使用 FAT JAR 的替代方案

尽管胖 JAR 带来了便利,但在某些场景下,可能有更合适的替代方案来满足项目需求:

  • 模块化 JAR:对于 JDK 9 及更高版本的项目,可以考虑使用模块化 JAR 来管理项目依赖。模块化 JAR 能更精细地控制依赖关系,减少资源浪费。
  • Spring Boot Thin Launcher:适合 Spring Boot 项目,该工具可以在保持胖 JAR 部署便利性的同时,减少 JAR 文件体积。Thin Launcher 会将依赖项单独存储并按需加载,避免了胖 JAR 的冗余。
  • Docker 容器化:对于分布式系统或微服务,Docker 容器是一种更合适的解决方案。将应用程序打包到 Docker 容器中可以保证依赖项的隔离性,减少资源冲突,适用于大规模部署。
七、总结

maven-shade-plugin 是一个功能强大的插件,可以帮助你将项目及其依赖打包成一个胖 JAR 文件。在实际使用中,通过合并资源、排除签名文件和重命名包路径,可以构建出无冲突的可执行 JAR,从而简化部署流程。

相关推荐
xoxo-Rachel几秒前
(超级详细!!!)解决“com.mysql.jdbc.Driver is deprecated”警告:详解与优化
java·数据库·mysql
乌啼霜满天2493 分钟前
JDBC编程---Java
java·开发语言·sql
色空大师15 分钟前
23种设计模式
java·开发语言·设计模式
闲人一枚(学习中)16 分钟前
设计模式-创建型-建造者模式
java·设计模式·建造者模式
2202_7544215433 分钟前
生成MPSOC以及ZYNQ的启动文件BOOT.BIN的小软件
java·linux·开发语言
蓝染-惣右介36 分钟前
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
java·数据库·tomcat·mybatis
小林想被监督学习37 分钟前
idea怎么打开两个窗口,运行两个项目
java·ide·intellij-idea
HoneyMoose39 分钟前
IDEA 2024.3 版本更新主要功能介绍
java·ide·intellij-idea
我只会发热40 分钟前
Java SE 与 Java EE:基础与进阶的探索之旅
java·开发语言·java-ee
是老余42 分钟前
本地可运行,jar包运行错误【解决实例】:通过IDEA的maven package打包多模块项目
java·maven·intellij-idea·jar