如何在Maven项目中包含本地jar文件

31

我不想将几个JAR文件安装到Maven存储库中(本地和远程都包括)。具体来说,我有几个JAR文件位于

c:\work\projects\myapp\src\main\webapp\WEB-INF\lib\test.jar

c:\work\projects\myapp\src\main\webapp\WEB-INF\lib\test2.jar

当使用NetBeans打开/编辑时,如何将它们包含到我的项目中?


5
我希望我能够摧毁、焚毁并将所有鼓励使用“系统”范围依赖项的问题送到地狱。我一直在反对这种做法,但可悲的是,它并没有起到什么作用... - Pascal Thivent
4个回答

68

虽然使用systemPath引用可以起作用,但最好创建一个本地仓库。 幸运的是,这很容易做到。

创建一个保存在公共仓库中不可用的jar的本地仓库

注意:我使用Eclipse,因此一些说明是特定于Eclipse的。 大多数都可以很容易地普遍适用。


假设

  • 该jar由Maven在另一个项目中创建,具有以下特征...

<groupId>com.foo</groupId>
<artifactId>test</artifactId>
<version>0.1.1</version>
<packaging>jar</packaging>

在需要访问这些jar包的项目中

  • 在项目的基础目录下创建存储库目录
  • 对于每个要本地访问的jar包...
    • 添加每个groupID级别的目录(例如/repo/com/foo
    • 添加该jar包的名称(也称为artifactId),但不包含版本号(例如/repo/com/foo/test
    • 添加该jar包的版本目录(例如/repo/com/foo/test/0.1.1
    • 将jar包放在该目录下(例如/repo/com/foo/test/0.1.1/test-0.1.1.jar

在pom.xml文件中(用于需要访问这些jar包的项目)

  • 定义本地存储库

<repositories>
  <repository>
    <id>data-local</id>
    <name>data</name>
    <url>file://${project.basedir}/repo</url>
  </repository>
</repositories>
  • 添加本地jar的依赖项。根据我们上面的示例,这将是...

  • <dependency>
      <groupId>com.foo</groupId>
      <artifactId>test</artifactId>
      <version>0.1.1</version>
    </dependency>
    

    重建

    • 右键点击 pom.xml -> 运行为 -> Maven 构建

    如果您只想让子模块中的JAR包获得访问权限,该怎么做呢?我按照说明在子模块的POM文件中添加了仓库定义,但是Maven在构建时似乎忽略了这个仓库。 - Niel de Wet
    真糟糕,我的打包文件是 pom 格式的,所以无法导入。将它改为 jar 格式,并运行 mvn clean install -U 命令后,就可以将其作为 Maven 的 <dependency> 添加到项目中了。 - prayagupa
    这是正确的答案;它遵循了Maven的理念,并且运行得非常好。 - Jonathan E. Landrum
    2
    对于Maven 3,还需要做一些其他事情,比如将jar重命名以包含版本号,并在每个目录中添加pom文件。幸运的是,有人已经在这里写了 https://gist.github.com/timmolderez/92bea7cc90201cd3273a07cf21d119eb - hello_earth
    这种方法适用于<descriptorRef>jar-with-dependencies</descriptorRef>,而<scope>system</scope>方法则不适用。 - Joe C
    1
    @hello_earth 尽管使用 Maven 3,JAR 文件需要在其名称中添加版本号作为后缀,但无需额外的 POM 文件! - Reto

    26

    你考虑过将这两个JAR文件添加为 system依赖项 吗?例如:

    <project>
      ...
      <dependencies>
        <dependency>
          <groupId>sun.jdk</groupId>
          <artifactId>tools</artifactId>
          <version>1.5.0</version>
          <scope>system</scope>
          <systemPath>${java.home}/../lib/tools.jar</systemPath>
        </dependency>
      </dependencies>
      ...
    </project>
    

    需要注意的是,这并不被推荐使用,并且应该非常谨慎地使用,如果有必要的话。


    1
    @Pascal Thivent:尽管您说我应该得到-10分,但我还是点赞了您的评论。 :) 我完全同意您的观点。我写下我的答案是基于@cometta使用它的原因。就个人而言,当我提问时,我讨厌有人会说“但你不应该那样做!”。我会更新我的答案,提到这是极不推荐的。 - The Alchemist
    1
    也许我评论的最后一部分并不必要(请注意,我实际上没有对您的答案进行投票)。至少,这不是在呼吁惩罚,而更多地是因为沮丧而尖叫 :) 我会重新发布一个更友好的版本。 - Pascal Thivent
    10
    这确实是一个非常 邪恶 的做法,强烈不建议使用。每当有人使用它时,上帝就会杀死一个Maven开发者。 - Pascal Thivent
    4
    我不像你那样强烈反对这种做法。在源代码控制的构建、无法访问本地maven仓库和团队项目的情况下,这是提供公共仓库中没有的依赖项的唯一明智解决方案。 - jfernand
    @jfernand - “这是唯一明智的解决方案…” 其实,这并不是唯一明智的解决方案。请看其他答案。 - Stephen C
    这种使用 <id>data-local</id> 的方法适用于 <descriptorRef>jar-with-dependencies</descriptorRef>,而 <scope>system</scope> 的方法则不适用。 - Joe C

    14

    过去,我通过在项目本身中创建“本地”仓库目录树,并声明一个相对于项目路径的本地仓库,来实现这一点。

    但那是一种hack。 (可能并不那么hacky-根据@Pascal的评论。 尽管使用 Maven 已有一年左右,但我仍然是个新手。)


    3
    这个“解决方案”比邪恶的系统范围“黑客技巧”好多了。人们在不明白它带来的危害的情况下继续使用系统范围(并推荐它),这令人沮丧。 - Pascal Thivent
    很高兴听到这对你有用。你能否更新你的答案,解释一下我如何让这个技巧对我起作用? - Jason R. Coombs

    7

    其他的答案对我都没有用,我必须运行一个稍微不同的命令...

    mvn deploy:deploy-file -Durl=file:///path/to/yourproject/repo/ -Dfile=mylib-1.0.jar -DgroupId=com.example -DartifactId=mylib -Dpackaging=jar -Dversion=1.0
    

    查看完整步骤,请参阅本文:https://devcenter.heroku.com/articles/local-maven-dependencies


    1
    如果您有一个用于本地jar的pom.xml文件(例如,因为您自己构建了它),那么您可以使用-DpomFile=<path-to-pom>指向该文件。然后,groupIdartifactIdversionpackaging参数将从pom文件中获取。请参阅https://maven.apache.org/guides/mini/guide-3rd-party-jars-remote.html。 - snark

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接