首页 > 解决方案 > maven 着色是如何工作的?

问题描述

在这篇问答文章中,我们将尝试回答以下问题 -

  1. 什么是maven中的阴影?
  2. maven-shade-plugin什么,用途是什么?
  3. 如何配置maven-shade-plugin实现遮光?

标签: maven

解决方案


1. 什么是阴影?

在 的上下文中maven,着色是一个过程,您可以通过该过程更改项目所依赖的某些依赖项的包名称。这样做的主要原因之一是解决依赖版本冲突。

考虑一下 - 您的项目依赖于特定版本的依赖项,例如com.fasterxml.jackson:jackson-databind- v2.9.10。您构建了一个 uber jar,将依赖项打包到服务的工件中。现在,假设您运行服务的主机提供了一个运行时环境,该环境提供com.fasterxml.jackson:jackson-databind- v2.6.7

我们有问题。在类路径上使用同一个库的两个版本,我们将遇到运行时错误和不可预知的行为。例如,您的代码调用了of 中的FAIL_ON_TRAILING_TOKENS字段,但该字段在 v2.9.10com.fasterxml.jackson:jackson-databindcom.fasterxml.jackson:jackson-databind-v2.6.7中不存在。所以本质上,我们有两个版本的com.fasterxml.jackson.databind.DeserializationFeature.java类。运行时不知道要拉哪一个,在这种情况下,您很可能会在运行时看到以下错误 -

    java.lang.NoSuchFieldError: FAIL_ON_TRAILING_TOKENS

那不好。在生产环境中运行代码时,您希望它是可预测的并且在您的控制之下。

那么,我们如何解决这个问题呢?阴影来拯救。通过阴影我们改变了类的“完全限定名” ——所以我们将有两个不同DeserializationFeature.java的类,而不是有两个版本的类——com.fasterxml.jackson.databing.DeserializationFeature.java

  1. com.fasterxml.jackson.databind.DeserializationFeature.java
  2. shaded-base.com.fasterxml.jackson.databind.DeserializationFeature.java

将应用于工件及其中的所有类shaded-base的前缀在哪里。让我们看看它实际上是如何完成的。maven-shade-plugincom.fasterxml.jackson:jackson-databind:2.9.10


2.Maven-Shade-Plugin

现在我们已经简单地熟悉了什么是着色以及何时使用它,让我们深入了解一下maven-shade-plugin它本身。

2.a) 使用构建一个 uber jarmaven-shade-plugin

除了着色之外,maven-shade-plugin还可以用来构建一个超级罐子,也称为“胖”罐子。uber jar 是一个 jar,您可以在其中打包项目所需的几乎所有依赖项。

让我们从一个例子开始。检查项目<dependencies>所需lake-tahoe 通过使用maven-shade-plugin我们将依赖项打包到lake-tahoe项目的最终工件中。你可以自己做。只需克隆存储库,然后运行以下命令 -

➜  lake-tahoe (master) mvn clean install

这将lake-tahoe-<version>-SNAPSHOT.jartarget/目录中创建。现在,让我们检查jackson文件是否“打包”在该工件中;出于本文的目的,我们将检查该DeserializationFeature.java文件。

➜  lake-tahoe (master) jar tf target/lake-tahoe-1.0.2-SNAPSHOT.jar | grep DeserializationFeature
com/fasterxml/jackson/databind/DeserializationFeature.class

是的。我们看到maven-shade-plugin将项目的依赖包打包在 uber jar 中。


2.b) 对依赖项进行着色。

我们可以使用<relocations>插件的元素来遮蔽或“重新打包”依赖项。检查truckee-river项目的pom.xml配置,看看我们是如何实现的。克隆 repo 并运行以下命令 -

truckee-river (master) mvn clean install

让我们检查一下truckee-riveruber jar 的内容。

➜  truckee-river (master) ✗ jar tf target/truckee-river-1.0.2-SNAPSHOT.jar | grep DeserializationFeature
com/water/bodies/fasterxml/jackson/databind/DeserializationFeature.class

如您所见,中的所有类com.fasterxml.jackson都已“重新定位”到com.water.bodies.fasterxml.jackson. 所以,这就是阴影。


2.c) 使用带阴影的同一库的两个版本

让我们来看看这个lake-pyramid项目。它拉入v2.6.7图书馆com.fasterxml.jackson:jackson-databind,也拉入truckee-river项目。正如我们在 #2.b 部分中看到的那样,truckee-river拉入lake-tahoe工件,然后v2.9.10com.fasterxml.jackson:jackson-databind. 然而,truckee-river项目遮蔽com.fasterxml.jackson并重新定位它,实际上创建了一个新的“完全合格的类”。

克隆lake-pyramid,您可以自己看到阴影和v2.6.7版本都打包在lake-pyramid的最终工件中。

➜  lake-pyramid (master) mvn clean install
// creates the `lake-pyramid-1.0.0-SNAPSHOT.jar`
(base) ➜  lake-pyramid (master) jar tf target/lake-pyramid-1.0.0-SNAPSHOT.jar | grep DeserializationFeature
com/water/bodies/fasterxml/jackson/databind/DeserializationFeature.class
com/fasterxml/jackson/databind/DeserializationFeature.class

所以,差不多就是这样。自己在本地尝试这些示例,您会感觉更舒服。

琐事特拉基河是太浩湖的唯一出水口,它排干了内华达山脉的一部分,流入大盆地的金字塔湖。


推荐阅读