maven-shade-plugin的用途是什么,你为什么要重新定位Java包?

2022-08-31 04:53:07

我发现maven-shade-plugin被用在某人的pom.xml。我以前从未使用过maven-shade-plugin(我是Maven n00b),所以我试图理解使用它的原因以及它的作用。

我看了Maven文档,但是我无法理解这种说法:

该插件提供了将工件打包到uber-jar中的功能,包括其依赖项以及着色 ( 即重命名 - 某些依赖项的包。

页面上的文档似乎不是很适合新手。

什么是“超级罐子”?为什么有人想做一个?重命名依赖项的包有什么意义?我试图浏览maven-shade-plugin apache页面上的示例,例如“为Uber Jar选择内容”,但我仍然无法理解“着色”正在完成什么。

任何指向说明性示例/用例的指针(并解释为什么在这种情况下需要着色 - 它解决了什么问题)将不胜感激。最后,我应该什么时候使用maven-shade-plugin?


答案 1

简而言之,Uber JAR是一个包含所有内容的JAR。

通常在 Maven 中,我们依赖于依赖关系管理。工件仅包含其自身的类/资源。Maven将负责根据项目的构建时间找出项目的所有工件(JAR等)。

uber-jar是获取所有依赖项的东西,并提取依赖项的内容,并将它们与项目本身的类/资源放在一个大JAR中。通过拥有这样的超级jar,它很容易执行,因为你只需要一个大JAR而不是大量的小JAR来运行你的应用程序。在某些情况下,它还简化了分发。

只是一个旁注:避免使用uber-jar作为Maven依赖项,因为它破坏了Maven的依赖项解析功能。通常,我们只为最终工件创建一个uber-jar,用于实际部署或手动分发,而不是用于放入Maven存储库。


更新:我刚刚发现我还没有回答问题的一部分:“重命名依赖项的包有什么意义?以下是一些简短的更新,希望能帮助有类似问题的人。

创建一个易于部署的超级 jar 是 shade 插件的一个用例。还有其他涉及包重命名的常见用例。

例如,我正在开发库,它依赖于库的特定版本(例如1.0)。假设我不能使用其他版本的lib(因为API更改或其他技术问题等)。如果我在 Maven 中简单地声明为 的依赖关系,则可能会遇到问题:项目依赖于 ,并且还依赖于 (并且它不能使用,因为需要在 中使用新功能)。这是两难的困境:应该使用(哪个代码不起作用)还是(哪个代码不起作用)?FooBarBarBar:1.0FooQuxFooBar:2.0Bar:1.0QuxBar:2.0QuxBar:1.0QuxBar:2.0Foo

为了解决这个问题,开发者可以选择使用shade插件来重命名其用法,这样jar中的所有类都嵌入到jar中,并且嵌入类的包从改为。通过这样做,可以安全地依赖于,因为现在不再依赖于,并且它正在使用位于另一个包中的“已更改”的副本。FooBarBar:1.0FooBarcom.barcom.foo.barQuxBar:2.0FooBarBar

enter image description here


答案 2

我最近在想,为什么 elasticsearch 会遮蔽和重新定位一些(但不是全部)它的依赖项。以下是项目维护者@kimchy的解释:

着色部分是有意的,我们在elasticsearch中使用的阴影库是elasticsearch的所有意图和目的部分,使用的版本与elasticsearch公开的内容以及它如何使用库的方式密切相关,基于库如何工作(以及版本之间的变化),netty和番石榴是很好的例子。

顺便说一句,我实际上提供了几个弹性搜索罐没有问题,一个带有lucene没有阴影,另一个带有Lucene阴影。不知道如何用maven来做。例如,我不想提供一个不遮挡netty/jackson的版本,因为elasticsearch对它们的深度使用(例如,与使用更少的netty相比,使用即将推出的缓冲改进与任何先前版本的netty相比,实际上将使用更多的内存)。

-- https://github.com/elasticsearch/elasticsearch/issues/2091#issuecomment-7156766

另一个来自drawr:

着色对于使我们的依赖项(特别是netty,lucene,番石榴)靠近我们的代码非常重要,这样即使上游提供商落后,我们也可以解决问题。我们可能会分发代码的模块化版本,这将有助于解决您的特定问题(例如#2091),但我们不能简单地删除此时的阴影依赖项。您可以根据需要构建本地版本的ES,直到有更好的解决方案。

-- https://github.com/elasticsearch/elasticsearch/pull/3244#issuecomment-20125452

所以,这是一个用例。至于一个说明性的例子,下面是如何在elasticsearch的pom.xml(v0.90.5)中使用maven-shade-plugin的。这些行指示它将哪些依赖项拉入uber JAR(基本上,当目标elasticsearch jar生成时,它们被解压缩并与elasticsearch自己的类一起重新打包。(如果您还不知道这一点,JAR文件只是一个ZIP文件,其中包含程序的类,资源等以及一些元数据。您可以提取一个以查看它是如何组合在一起的。artifactSet::include

这些行是相似的,不同之处在于在每种情况下,它们还将指定的替换应用于依赖项的类 - 在本例中,将它们置于 。relocations::relocationorg.elasticsearch.common

最后,该部分从目标JAR中排除了一些不应该在那里的东西 - 例如JAR元数据,ant构建文件,文本文件等,它们与某些依赖项一起打包,但不属于uber JAR。filters

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>2.1</version>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>shade</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <minimizeJar>true</minimizeJar>
            <artifactSet>
                <includes>
                    <include>com.google.guava:guava</include>
                    <include>net.sf.trove4j:trove4j</include>
                    <include>org.mvel:mvel2</include>
                    <include>com.fasterxml.jackson.core:jackson-core</include>
                    <include>com.fasterxml.jackson.dataformat:jackson-dataformat-smile</include>
                    <include>com.fasterxml.jackson.dataformat:jackson-dataformat-yaml</include>
                    <include>joda-time:joda-time</include>
                    <include>io.netty:netty</include>
                    <include>com.ning:compress-lzf</include>
                </includes>
            </artifactSet>
            <relocations>
                <relocation>
                    <pattern>com.google.common</pattern>
                    <shadedPattern>org.elasticsearch.common</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>gnu.trove</pattern>
                    <shadedPattern>org.elasticsearch.common.trove</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>jsr166y</pattern>
                    <shadedPattern>org.elasticsearch.common.util.concurrent.jsr166y</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>jsr166e</pattern>
                    <shadedPattern>org.elasticsearch.common.util.concurrent.jsr166e</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>org.mvel2</pattern>
                    <shadedPattern>org.elasticsearch.common.mvel2</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>com.fasterxml.jackson</pattern>
                    <shadedPattern>org.elasticsearch.common.jackson</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>org.joda</pattern>
                    <shadedPattern>org.elasticsearch.common.joda</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>org.jboss.netty</pattern>
                    <shadedPattern>org.elasticsearch.common.netty</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>com.ning.compress</pattern>
                    <shadedPattern>org.elasticsearch.common.compress</shadedPattern>
                </relocation>
            </relocations>
            <filters>
                <filter>
                    <artifact>*:*</artifact>
                    <excludes>
                        <exclude>META-INF/license/**</exclude>
                        <exclude>META-INF/*</exclude>
                        <exclude>META-INF/maven/**</exclude>
                        <exclude>LICENSE</exclude>
                        <exclude>NOTICE</exclude>
                        <exclude>/*.txt</exclude>
                        <exclude>build.properties</exclude>
                    </excludes>
                </filter>
            </filters>
        </configuration>
    </plugin>
</plugins>

推荐