我在我的项目中使用了 maven shade 插件来重新定位一个包下的所有依赖 jar 类,例如 org.shade.*
当我尝试在其他应用程序中使用该阴影 jar 作为 maven 依赖项时,它会提取依赖项 jar。
我的期望是当 uber/shaded jar 包含为 maven 依赖项时,它不应该拉取任何其他依赖的类 jar,因为这些类已经重新打包在 shaded jar 中。
我在我的项目中使用了 maven shade 插件来重新定位一个包下的所有依赖 jar 类,例如 org.shade.*
当我尝试在其他应用程序中使用该阴影 jar 作为 maven 依赖项时,它会提取依赖项 jar。
我的期望是当 uber/shaded jar 包含为 maven 依赖项时,它不应该拉取任何其他依赖的类 jar,因为这些类已经重新打包在 shaded jar 中。
经典场景是:
dependency
中的元素pom.xml
),然后将它们打包在一个 uber-jar 中作为 Maven 工件dependency
另一个项目的依赖项(元素)时,Maven 将检查其<artifact>-<version>.pom
文件(与最终工件一起发布到 Maven 存储库中),该文件基本上是其原始pom.xml
文件的重命名副本,其中依赖项(dependency
元素) 被声明(确切地说是打包到 uber-jar 中的依赖项)。由于您已经将它们打包,因此您希望忽略该.pom
文件(及其dependencies
元素),为此您需要添加exclusions
如下:
<dependency>
<groupId>com.sample</groupId>
<artifactId>something-uber</artifactId>
<version>some-version</version>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
注意:上述功能仅在 Maven 之后可用3.2.1
。
因此,您向 Maven 明确表示您不想要任何传递依赖,并且Maven 依赖调解不会触发它们。
附带说明:将 uber-jar 作为项目的依赖项并不是一个好习惯:它只会使维护变得更加困难,因为您无法通过依赖项目的顺序dependencyManagement
或dependencies
顺序来控制传递依赖项。因此,每当依赖项(其传递的一个)需要维护(更改版本等)并且对依赖项目的控制要少得多(再次,更难的维护)时,您总是需要重新打包 uber jar。
由于生成 uber jar 的源项目上的 pom.xml声明了传递依赖项,如果您将其作为依赖项包含到外部项目中,那么 Maven 将尝试获取这些(即使这些已经包含在 uber jar 中)。
我分享了一个解决方案,让您避免明确排除所有传递依赖项,包括它到外部项目中,正如@A_DiMatteo 在他的解决方案中所解释的那样(我也同意他关于避免使用 uber jar 作为依赖项,如果不是绝对必要的话)由于某些原因 )。因此,您应该能够在不使用排除元素的情况下包含您的 uber jar 依赖项,如下所示:
<dependency>
<groupId>com.sample</groupId>
<artifactId>something-uber</artifactId>
<version>some-version</version>
</dependency>
前提:我的目标是在我的存储库中提供uber(没有在 pom 上声明传递依赖)和瘦jar。所以我的解决方案“A”是基于这种情况的,目前有阴影 jar 在存储库上上传 2 次的限制。
- 要仅提供uber jar,请参阅下面的“B”解决方案
- 有关“A”限制的可能解决方案,请参阅末尾的更新部分
1- 在您的源项目上,在您的东西模块 pom.xml 上配置以下maven-shade-plugin,如下所示:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>something-uber-${project.version}</finalName>
</configuration>
</execution>
</executions>
</plugin>
然后使用build-helper-maven-plugin插件在模块上附加带有“uber”分类器的新工件:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<id>attach-artifacts</id>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>
${project.build.directory}/something-uber-${project.version}.jar
</file>
<classifier>uber</classifier>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
这将作为 maven 安装阶段的结果在target/目录中生成以下两个 jar:
40K something-0.1.0.jar
7M something-uber-0.1.0.jar
警告:然后执行 Maven 部署阶段,两个 jar 都将上传到存储库!这里的目标应该是只上传薄 jar跳过部署阴影 jar以便将其保留为本地工件(请参阅末尾的UPDATE部分以获取可能的修复)
2-然后在您的源项目上创建另一个名为something-uber的模块,添加以下依赖项和插件:
<dependencies>
<dependency>
<groupId>com.sample</groupId>
<artifactId>something</artifactId>
<version>${project.version}</version>
<classifier>uber</classifier>
<exclusions>
<exclusion>
<artifactId>*</artifactId>
<groupId>*</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
在包含依赖项时注意以下几点:
在此模块上执行最后的 maven 部署阶段,阴影 jar 将被上传到存储库,您我们将能够将其作为依赖项添加到外部项目中,如下所示:
<dependency>
<groupId>com.sample</groupId>
<artifactId>something-uber</artifactId>
<version>0.1.0</version>
</dependency>
从解决方案“A”开始,如果您想避免在存储库上提供瘦 jar,则应避免在第 1 点上在 maven-shade-plugin 配置 中指定finalName ,因此也应避免使用build-helper-maven-plugin插件,因为没有不是要附加的新工件。这样做,部署模块,你将只有目标/上的 uber jar 作为默认值(没有分类器):
7M something-0.1.0.jar
您还应该跳过上传,否则您还会在这里上传两个胖罐子(something-0.1.0.jar和something-uber-0.1.0.jar)。为此,在同一模块上添加以下插件:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
在第 2 点的最后,避免在添加依赖项时指定分类器,如下所示:
<dependencies>
<dependency>
<groupId>com.sample</groupId>
<artifactId>something</artifactId>
<version>${project.version}</version>
<exclusions>
<exclusion>
<artifactId>*</artifactId>
<groupId>*</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
在搜索了一段时间没有成功的解决方案后,我决定从 GitHub 分叉maven-deploy-plugin插件并开发一个新功能,以便跳过在第一个模块上创建的阴影 jar,添加配置如下的插件:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-SNAPSHOT</version>
<configuration>
<skipAttachedArtifacts>
<artifact>
<groupId>com.sample</groupId>
<artifactId>something</artifactId>
<version>${project.version}</version>
<packaging>jar</packaging>
<classifier>uber</classifier>
</artifact>
</skipAttachedArtifacts>
</configuration>
</plugin>
当前使用maven-deploy-plugin插件,所有工件都被排除在部署之外,而这里的目标是只排除一个特定的工件。在我的 fork 中,我引入了“skipAttachedArtifacts”配置参数,以便指定要从部署中排除的附加工件。
这是我在 GitHub 上的分叉项目的链接: https ://github.com/gregorycallea/maven-deploy-plugin
这里是我在 apache 插件项目上提交的拉取请求的链接: https ://github.com/apache/maven-deploy-plugin/pull/3