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,从而简化部署流程。

相关推荐
缺点内向3 小时前
Java:创建、读取或更新 Excel 文档
java·excel
带刺的坐椅3 小时前
Solon v3.4.7, v3.5.6, v3.6.1 发布(国产优秀应用开发框架)
java·spring·solon
四谎真好看5 小时前
Java 黑马程序员学习笔记(进阶篇18)
java·笔记·学习·学习笔记
桦说编程5 小时前
深入解析CompletableFuture源码实现(2)———双源输入
java·后端·源码
java_t_t5 小时前
ZIP工具类
java·zip
lang201509285 小时前
Spring Boot优雅关闭全解析
java·spring boot·后端
pengzhuofan6 小时前
第10章 Maven
java·maven
百锦再7 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说7 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多7 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring