什么是maven-shade-plugin用于,为什么你想要重新定位java包?

我发现在某人的pom.xml中使用了maven-shade-plugin。 我以前从来没有使用maven-shade-plugin(我是maven n00b),所以我试图理解使用它的原因以及它的作用。 我看了一下maven文档 ,但是我不明白这个说法:“这个插件提供了将工件打包在一个超级jar文件中的function,包括它的依赖关系,以及对一些依赖关系的包进行遮罩 – 即重命名。 “ 该页面上的文档似乎不是新手友好的。

什么是“超级jar子”? 为什么有人想要做一个? 重命名依赖关系的包有什么意义? 我试图通过maven-shade-plugin apache页面上的例子,例如“为Uber Jarselect内容”,但是我仍然不明白“阴影”是如何实现的。

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

简言之,Uber JAR是一个包含所有东西的JAR。

通常在Maven中,我们依赖于依赖pipe理。 工件只包含其自身的类/资源。 Maven将负责找出所有项目取决于项目的build立时间的工件(JAR等)。

一个超级jar是取得所有依赖关系的东西,并提取依赖关系的内容,并将它们与项目本身的类/资源放在一个大的JAR中。 通过使用这种超级jar,执行起来非常简单,因为只需要一个大的JAR而不是大量的小JAR来运行你的应用程序。 在某些情况下它也可以轻松分配。

只是一个侧面说明。 避免使用uber-jar作为Maven依赖项,因为它破坏了Maven的依赖性parsingfunction。 通常情况下,我们只为实际部署或手动分发的最终构件创build超级jar,而不是用于放入Maven存储库。


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

为便于部署创buildUber-jar是一个阴影插件的用例。 还有其他一些涉及包重命名的常见用例。

例如,我正在开发Foo库,该库取决于Bar库的特定版本(例如1.0)。 假设我不能使用其他版本的Bar lib(因为API更改或其他技术问题等)。 如果我只是将Bar:1.0声明为Foo在Maven中的依赖关系,则可能会出现问题: Qux项目取决于Foo ,还有Bar:2.0 (因为Qux需要使用,所以它不能使用Bar:1.0 Bar:2.0新functionBar:2.0 )。 这里是两难: Qux应该使用Bar:1.0Qux的代码不行)或者Bar:2.0Foo的代码不行)?

为了解决这个问题, Foo开发者可以select使用shade插件来重命名Bar使用,这样Bar:1.0 jar中的所有类都被embedded到Foo jar中,embedded的Bar类的包从com.barcom.foo.bar 。 通过这样做, Qux可以安全地依赖于Bar:2.0因为现在Foo不再依赖于Bar ,它使用的是位于另一个包中的“已更改” Bar自己的副本。

我最近在想自己为什么弹性search能够遮蔽和重新定位一些(但不是全部)它的依赖关系。 以下是项目维护人员@kimchy的解释:

阴影部分是故意的,我们在elasticsearch中使用的阴影库是针对弹性search的所有意图和目的部分的,所使用的版本与弹性search公开的内容紧密联系,以及如何使用基于内部如何工作的内部库(以及版本之间的变化),netty和番石榴是很好的例子。

顺便说一句,我没有问题,实际上提供了几个jar子的elasticsearch,一个lucene没有阴影,一个与Lucene阴影。 不知道如何与maven做到这一点。 例如,我不想提供一个不会影响netty / jackson的版本,因为elasticsearch对它们有着深刻而有效的用法(例如,使用即将到来的缓冲区改进,除了当前版本的netty之外,实际上使用更多的内存相比,使用更less)。

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

另一个来自drewr

阴影对于保持我们的依赖关系(特别是netty,lucene,guava)接近我们的代码非常重要,这样即使上游提供者滞后,我们也可以解决问题。 我们可能会分发代码的模块化版本,这将有助于解决您的特定问题(例如#2091),但是我们现在不能简单地删除阴影的依赖项。 你可以为你的目的build立一个本地版本的ES,直到有一个更好的解决scheme。

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

所以,这是一个用例。 至于说明性的例子,下面是在elasticsearch的pom.xml(v0.90.5)中如何使用maven-shade-plugin。 artifactSet::include行指示它将什么依赖关系拉入到超级JAR中(基本上,当弹性searchjar被生成时,它们被解压并重新封装在elasticsearch自己的类中)(如果你不知道这个, JAR文件只是一个ZIP文件,包含程序的类,资源等,还有一些元数据,你可以从中提取一个来看看它是如何放在一起的。)

relocations::relocation行是相似的,除了在每种情况下,他们也将指定的替代应用到依赖的类 – 在这种情况下,将它们org.elasticsearch.common

最后, filters部分从目标JAR中排除了一些不应该存在的东西 – 比如JAR元数据,ant构build文件,文本文件等,这些东西被封装在一些依赖关系中,但不属于超级JAR 。

 <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> 

小警告

虽然这并不能说明为什么要使用maven-shade-plugin(因为所选的答案描述的非常好),所以我想说明一下,我遇到了问题。 它改变了JAR(因为它正在做什么),并导致我的软件退化。

所以,而不是使用这个(或maven-jarjar插件),我已经使用JarJar的二进制,似乎没有问题。

我在这里发布我的解决scheme,因为它花了我一些时间来find一个体面的解决scheme。


下载JarJar的JAR文件

您可以从这里下载jar: https : //code.google.com/p/jarjar/在左边的菜单中有一个链接来下载它。


如何使用JarJar将一个JAR的类从一个包重定位到另一个包

在这个例子中,我们将把包从“com.fasterxml.jackson”更改为“io.kuku.dependencies.com.fasterxml.jackson”。 – 源JAR被称为“jackson-databind-2.6.4.jar”,新的被修改(目标)JAR被称为“kuku-jackson-databind-2.6.4.jar”。 – “jarjar”JAR文件在1.4版本中

  1. 创build一个“rules.txt”文件。 文件的内容应该是(注意'@'字符之前的时间段):rule com.fasterxml.jackson。** io.kuku.dependencies.com.fasterxml.jackson。@ 1

  2. 运行以下命令:java -jar jarjar-1.4.jar process rules.txt jackson-databind-2.6.4.jar kuku-jackson-databind-2.6.4.jar


将修改后的JAR安装到本地存储库

在这种情况下,我正在安装“c:\ my-jars \”文件夹中的3个文件。

mvn install:install-file -Dfile = C:\ my-jars \ kuku-jackson-annotations-2.6.4.jar -DgroupId = io.kuku.dependencies -DartifactId = kuku-jackson-annotations -Dversion = 2.6.4 – Dpackaging =jar子

mvn install:install-file -Dfile = C:\ my-jars \ kuku-jackson-core-2.6.4.jar -DgroupId = io.kuku.dependencies -DartifactId = kuku-jackson-core -Dversion = 2.6.4 – Dpackaging =jar子

mvn install:install-file -Dfile = C:\ my-jars \ kuku-jackson-databind-2.6.4.jar -DgroupId = io.kuku.dependencies -DartifactId = kuku-jackson-annotations -Dversion = 2.6.4 – Dpackaging =jar子


在项目的pom中使用修改过的JAR

在这个例子中,这是项目pom中的“dependencies”元素:

 <dependencies> <!-- ================================================== --> <!-- kuku JARs --> <!-- ================================================== --> <dependency> <groupId>io.kuku.dependencies</groupId> <artifactId>kuku-jackson-annotations</artifactId> <version>2.6.4</version> </dependency> <dependency> <groupId>io.kuku.dependencies</groupId> <artifactId>kuku-jackson-core</artifactId> <version>2.6.4</version> </dependency> <dependency> <groupId>io.kuku.dependencies</groupId> <artifactId>kuku-jackson-databind</artifactId> <version>2.6.4</version> </dependency> </dependencies>