【问题标题】:How to get path to dependency jar with maven如何使用maven获取依赖jar的路径
【发布时间】:2015-03-22 05:43:03
【问题描述】:

给定一个简单的 Maven 项目,例如 JUnit 作为依赖项,我如何在本地 maven 存储库中获取 junit.jar 的完整文件路径?!

例如如何从神器junit:junit/Users/foobar/.m2/repository/junit/junit/4.11/junit-4.11.jar

【问题讨论】:

    标签: java maven dependencies


    【解决方案1】:

    一个 hacky 解决方案,使用 mvn dependency:build-classpath 和一些 unix shell 魔法从类路径中提取 jar 路径。

    我们有这样的pom.xml...

    <?xml version="1.0" encoding="UTF-8"?>
    <project>
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.mycompany</groupId>
      <artifactId>myproject</artifactId>
      <version>1.0-SNAPSHOT</version>
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    </project>
    

    然后我们生成一个build_classpath 文件。

    $ mvn dependency:build-classpath -Dmdep.outputFile=build_classpath
    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] Building myproject 1.0-SNAPSHOT
    [INFO] ------------------------------------------------------------------------
    [INFO]
    [INFO] --- maven-dependency-plugin:2.8:build-classpath (default-cli) @ myproject ---
    [INFO] Wrote classpath file '/Users/foobar/maven-test/build_classpath'.
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 1.050 s
    [INFO] Finished at: 2015-01-23T09:17:40+01:00
    [INFO] Final Memory: 11M/245M
    [INFO] ------------------------------------------------------------------------
    $ cat build_classpath
    /Users/foobar/.m2/repository/junit/junit/4.11/junit-4.11.jar:/Users/foobar/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar
    

    现在我们可以使用一些脚本 foo 从build_classpath 提取 jar 文件路径...

    $ cat build_classpath | perl -ne 'print "$1" if /(?:^|:)([^:]+?\/junit-[0-9\.]+\.jar)/'
    /Users/foobar/.m2/repository/junit/junit/4.11/junit-4.11.jar
    

    编辑

    在 OSX 中使用的更简单的 shell 命令,它简单地将每个条目拆分到自己的行中。对于所需的任何依赖项,grep 输出都很简单。请注意,该命令实际上使用换行符(换行到下一行)而不是换行符。

    $ tr ':' '
    ' < build_classpath; echo
    

    【讨论】:

    • 此解决方案非常适合一次性使用,无需更改您的 POM,这几乎总是我想要的方式。
    【解决方案2】:

    来自the following SO answer,看来最简单的就是使用antrun插件了。

    <plugin>
        <artifactId>maven-antrun-plugin</artifactId>
        <executions>
            <execution>
                <phase>process-resources</phase>
                <configuration>
                    <tasks>
                        <echo>${maven.dependency.junit.junit.jar.path}</echo>
                    </tasks>
                </configuration>
                <goals>
                    <goal>run</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    

    【讨论】:

    • antrun 目标&lt;echoproperties /&gt; 也很有用。
    • 这实际上是同事几个月前提出的解决方案,效果很好,这就是为什么我接受你的回答,Jim。
    【解决方案3】:

    maven 依赖插件有一个目标“属性”。来自documentation

    为每个项目依赖项设置指向工件文件的属性的目标。对于每个依赖项(直接和传递),将设置一个项目属性,该属性遵循 groupId:artifactId:type:[classifier] 形式并包含已解析工件的路径。

    所以这样的事情应该可以解决问题:

    <properties>
        <maven-dependency-plugin.version>3.1.1</maven-dependency-plugin.version>
    </properties>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>${maven-dependency-plugin.version}</version>
        <executions>
            <execution>
                <phase>initialize</phase>
                <goals>
                    <goal>properties</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    

    那么属性${junit:junit:jar}应该包含jar文件路径

    【讨论】:

    • 这其实是最好的答案。
    • 这在 Maven 中非常有效,例如在&lt;argLine&gt; 上使用 Surefire 中的这些属性时。不幸的是,在这种情况下,IntelliJ IDEA 错误地导入了&lt;argLine&gt;,无法解析合成属性以自动将它们用于运行配置。所以我最终定义了像&lt;bytebuddy.jar&gt;${settings.localRepository}/net/bytebuddy/byte-buddy/${bytebuddy.version}\byte-buddy-${bytebuddy.version}.jar&lt;/bytebuddy.jar&gt; 这样的属性,并在&lt;argLine&gt; 中使用它们。现在 IDEA 会自动导入正确的参数来运行单个测试。
    【解决方案4】:

    如果你想在你的运行代码中获取路径,你可以这样做:

    POM:

        <dependency>
            <groupId>com.github.nodyn</groupId>
            <artifactId>jvm-npm</artifactId>
            <version>a0c3f12</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.aether</groupId>
            <artifactId>aether-impl</artifactId>
            <version>1.1.0</version>
        </dependency>
                <dependency>
            <groupId>org.eclipse.aether</groupId>
            <artifactId>aether-transport-file</artifactId>
            <version>1.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.aether</groupId>
            <artifactId>aether-connector-basic</artifactId>
            <version>1.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-aether-provider</artifactId>
            <version>3.1.0</version>
        </dependency>
    

    代码:

    final String mavenRepositoryPath = "c:\\mvn\\repository";
    
    private static RepositorySystem newRepositorySystem() {
        DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator();
        locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class);
        locator.addService(TransporterFactory.class, FileTransporterFactory.class);
    
        locator.setErrorHandler(new DefaultServiceLocator.ErrorHandler() {
            @Override
            public void serviceCreationFailed(Class<?> type, Class<?> impl, Throwable exception) {
                throw new RuntimeException(exception);
            }
        });
    
        return locator.getService(RepositorySystem.class);
    }
    
    private static File getJvmNpmFile() {
        Artifact artifact = new DefaultArtifact("com.github.nodyn:jvm-npm:a0c3f12");
    
        DefaultRepositorySystemSession session = new org.eclipse.aether.DefaultRepositorySystemSession();
        RepositorySystem system = newRepositorySystem();
        ArtifactRequest request = new ArtifactRequest();
        request.setArtifact(artifact);
        //request.setRepositories(new ArrayList<>( Arrays.asList( new RemoteRepository.Builder( "central", "default", "http://central.maven.org/maven2/" ).build()) ));
        //request.setRepositories( new org.eclipse.aether.DefaultRepositorySystemSession().getLocalRepository() );
        LocalRepository localRepo = new LocalRepository(mvnRepositoryPath);
        session.setLocalRepositoryManager(system.newLocalRepositoryManager(session, localRepo));
    
        ArtifactResult result;
        try {
            result = system.resolveArtifact(session, request);
        } catch (ArtifactResolutionException ex) {
            throw new RuntimeException(ex);
        }
    
        //System.out.println("Resolved artifact " + artifact + " to " + result.getArtifact().getFile() + " from " + result.getRepository());
        return result.getArtifact().getFile();
    }
    

    【讨论】:

      【解决方案5】:

      路径构建为 $repository_dir/groupId/artifactId/version/artifactId-version.jar

      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      

      【讨论】:

      • 是的,当然...但是依赖项的安装位置实际上取决于调用mvn 的用户如何配置它的maven 安装。这可能是安静的不幸,例如在共享构建服务器等上。我正在寻找一些只输出 jar 所在位置的命令。
      • shared build servers. 是什么意思。输出给出了 junit 文件的位置。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-10
      • 1970-01-01
      • 2022-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多