21

由于两个依赖项之间的一些不兼容,我被迫制作我的一个依赖项的阴影版本。这意味着我的项目现在依赖于本地 .jar 文件。

在运行之前,我以前完全可以使用mvn install-file将此 .jar 安装到我的本地存储库mvn install

mvn org.apache.maven.plugins:maven-install-plugin:2.5.2:install-file -Dfile=lib/my-custom-jar-1.0.0.jar
mvn install

但是,我的项目现在将在自动构建服务器上,谁只会做mvn clean install而不会做其他事情。

找了半天,找到了几种解决方案,但没有一个是完美的。

我将在下面写下我找到的解决方案作为答案,但我发布这个问题是希望有人有更好的想法来解决这个问题。

4

3 回答 3

46

这是我尝试过的几个解决方案,但对我的使用并不好:

1. maven-安装-插件

这个想法是通过将其添加到 pom 中来添加 install-file 目标作为安装生命周期的一部分:

<plugin>
  <artifactId>maven-install-plugin</artifactId>
  <version>2.5.2</version>
  <executions>
    <execution>
      <phase>validate</phase>
      <goals>
        <goal>install-file</goal>
      </goals>
      <configuration>
        <file>lib/my-custom-jar-1.0.0.jar</file>
      </configuration>
    </execution>
  </executions>
</plugin>

[...]

<dependency>
  <groupId>org.me</groupId>
  <artifactId>my-custom-jar</artifactId>
  <version>1.0.0</version>
</dependency>

然而,即使是第一个目标,validateMaven 也会在 install-file 运行之前尝试解决依赖关系。

我看到了使用 clean 目标的想法。烦人的是,这在您执行单独的命令 ( mvn clean && mvn install) 时有效,但如果您在一个 mvn 命令 ( mvn clean install) 中执行这两项操作,Maven 将首先解决依赖关系。有没有办法解决这个问题?

2. 多模块项目

在这个 Stack Overflow 答案中看到的想法是,您在父 pom 中安装文件,并在您的子 pom.xml 中添加依赖项。Maven 只会单独解决依赖关系,所以这应该可以工作。

然而我的项目是一个单一的模块,为了解决这个问题而制作一个假父母似乎过于复杂和丑陋的黑客攻击。

3. 使用 basedir 的系统范围

<dependency>
  <groupId>org.me</groupId>
  <artifactId>my-custom-jar</artifactId>
  <version>1.0.0</version>
  <scope>system</scope>
  <systemPath>${basedir}/lib/my-custom-jar-1.0.0.jar</systemPath>
</dependency>

尽管这看起来完全是针对这种情况而制作的,但系统范围实际上希望依赖关系存在于您将运行项目的每个系统上,因此它不会被打包在 .war 中,从而使我的项目非-功能性。

4. addjars-maven-plugin

在此处找到的这个自定义插件在您的 .war 文件中包含一个 .jar,然后在编译期间将其添加到您的 pom 中。

<plugin>
  <groupId>com.googlecode.addjars-maven-plugin</groupId>
  <artifactId>addjars-maven-plugin</artifactId>
  <version>1.0.5</version>
  <executions>
    <execution>
      <goals>
        <goal>add-jars</goal>
      </goals>
      <configuration>
        <resources>
          <resource>
            <directory>${basedir}/lib</directory>
            <includes>
              <include>**/my-custom-jar-1.0.0.jar</include>
            </includes>
          </resource>
        </resources>
      </configuration>
    </execution>
  </executions>
</plugin>

这在大多数正常情况下都有效。但是,由于您没有在实际的 pom 中表明对自定义 .jar 的任何依赖关系,因此您的 IDE 将缺少很多类,因此您需要手动将自定义 .jar 添加为外部库。

这仍然有些 hacky,并且不适用于某些特殊情况(例如,用于 Jenkins 调试的 hpi:run 会引发一些错误)。另外,我更喜欢我的代码不依赖第三方插件。

5. 目录内 Maven 存储库

我在创建这篇文章后找到了这个解决方案,我对此非常满意。

这与在我的问题中执行命令的结果几乎相同mvn install-file,除了您通过在项目内部的存储库中安装自定义库来保存结果并将其保留为项目的一部分。

您将需要使用此命令预安装库。

mvn org.apache.maven.plugins:maven-install-plugin:2.5.1:install-file \
-Dfile=lib/cloudfoundry-client-lib-shaded-1.0.3.jar \
-DlocalRepositoryPath=lib

完成后,您的存储库将在 lib 文件夹中创建,您将不再需要执行此命令。

表明你想在你的 pom 中使用这个仓库:

<repository>
  <id>Local repository</id>
  <url>file://${basedir}/lib</url>
</repository>

[...]

<dependency>
  <groupId>org.me</groupId>
  <artifactId>my-custom-jar</artifactId>
  <version>1.0.0</version>
</dependency>

此解决方案迫使您向 SCM 提交一堆额外的文件夹,但这对我来说是一个可以控制的缺点,我对此感到满意。

于 2014-10-28T20:49:14.457 回答
1

在一个子项目中执行阴影(称为 S),它会吃掉您的问题依赖项的版本 (a),并产生您自己的 G/A/V'd 结果。配置 shade 以产生子项目的主要输出。换句话说,S 产生的 group:artifact:version 都与你需要两个版本的东西的坐标完全不同。

在您的其他子项目中,只需将 (S) 声明为依赖项即可获取着色版本,然后您也可以声明未着色的其他版本。

这一切都假设您在着色时重命名了包。

无需安装:任何东西。

于 2014-10-29T00:55:47.453 回答
0

在 maven-install-plugin 上使用 phase clean

<plugin>
  <artifactId>maven-install-plugin</artifactId>
  <version>2.5.2</version>
  <executions>
    <execution>
      <phase>**clean**</phase>
      <goals>
        <goal>install-file</goal>
      </goals>
      <configuration>
        <file>lib/my-custom-jar-1.0.0.jar</file>
      </configuration>
    </execution>
  </executions>
</plugin>

解析前执行mvn clean安装本地依赖

mvn clean

注意:mvn clean install不起作用(仅运行干净)

于 2020-04-22T10:45:28.727 回答