乐趣区

关于java:使用-Maven-Embedder-通过代码执行-maven-命令

如果有个需要是要通过代码调用 maven 命令,来上传 jar 包或进行其余操作,该如何实现?

调用命令行当然能够,maven 官网也有一个我的项目 Apache Maven Invoker 实现相似需要,但前提是服务运行的机器或者容器中须要有 maven。

大家可能都据说过 Write once, run anywhere. 如果没了 maven 环境就执行不了了,有没有更好的形式呢

Maven Embedder 也是 maven 官网的一个我的项目,如名字一样,是可嵌入的,也就是不须要依赖内部 maven。我的项目是个好我的项目,但问题就是官网提供的文档切实太少了。

以防被喷,这里没有说嵌入肯定是更好的计划,毕竟不可能把我的项目所需的所有依赖都打包到一起,还是要依据理论问题来抉择的。

依赖

依照官网其实只须要 maven-embedder 一个依赖就能够,但理论运行起来,会发现报很多错,这里也不啰嗦,间接放出残缺可用的依赖。

<dependency>
    <groupId>org.apache.maven</groupId>
    <artifactId>maven-embedder</artifactId>
    <version>3.6.3</version>
</dependency>
<dependency>
    <groupId>org.apache.maven</groupId>
    <artifactId>maven-compat</artifactId>
    <version>3.6.3</version>
</dependency>
<dependency>
    <groupId>org.apache.maven.resolver</groupId>
    <artifactId>maven-resolver-connector-basic</artifactId>
    <version>1.4.1</version>
</dependency>
<dependency>
    <groupId>org.apache.maven.resolver</groupId>
    <artifactId>maven-resolver-transport-http</artifactId>
    <version>1.4.1</version>
</dependency>

maven-compat 是一个用于放弃与 Maven2 兼容性的包。

maven-resolver-connector-basicmaven-resolver-transport-http 用于 deploy。如果只运行到 install,不须要 deploy,这两个依赖能够去掉。网上很多会用 aether 我的项目中的依赖,相似上面这种的

 <dependency>
  <groupId>org.eclipse.aether</groupId>
  <artifactId>aether-connector-basic</artifactId>
  <version>1.0.2.v20150114</version>
</dependency>
<dependency>
  <groupId>org.eclipse.aether</groupId>
  <artifactId>aether-transport-wagon</artifactId>
  <version>1.0.2.v20150114</version>
</dependency>

然而实际上 aether 这个我的项目曾经进行了,详见 Aether Termination Review,而 Apache Maven Artifact Resolver 就是替代者。

应用

应用的代码也很简略

public static void deploy(String path){MavenCli cli = new MavenCli();
    String mvnHome = MavenCli.USER_MAVEN_CONFIGURATION_HOME.getAbsolutePath();
    System.getProperties().setProperty("maven.multiModuleProjectDirectory", mvnHome);
    List<String> args = new ArrayList<>();
    args.add("clean");
    args.add("deploy");
    int status = 0;
    try {status = cli.doMain(args.toArray(new String[]{}), path, System.out, System.out);
    }catch (Exception e){logger.error(e.getMessage(),e);
        throw e;
    }
    if (status != 0) {throw new RuntimeException("maven 出错");
    }
}

maven.multiModuleProjectDirectory 这个零碎变量,如果设置了就无需设置了,但如果没有就须要设置,否则会报错。

另外因为 deploy 时波及服务器的账户和明码,可能须要配置文件,这里有两种解决方案:

  1. 通过 -s,--settings 来指定配置文件的门路。
  2. 把配置文件放到 maven home 中。

如果应用了明码加密,还波及 settings-security.xml 文件,这时用第一种就行不太通(次要我没胜利),把这两个文件都放到 maven home 是没啥问题的。默认的 maven home 就是用户目录下的 .m2 目录。

常见谬误

-Dmaven.multiModuleProjectDirectory system property is not set.

后面提到了,设置这个零碎变量就能够了,值为 maven home 对应的门路即可。

No implementation for org.apache.maven.repository.RepositorySystem was bound.

增加依赖,尽管这是个 maven 2 的兼容包,然而还没找到其余的可替代品。

<dependency>
    <groupId>org.apache.maven</groupId>
    <artifactId>maven-compat</artifactId>
    <version>3.6.3</version>
</dependency>

No connector factories available、No transporter factories registered

这两个都是部署过程中会报出的谬误,增加如下依赖即可解决

<dependency>
    <groupId>org.apache.maven.resolver</groupId>
    <artifactId>maven-resolver-connector-basic</artifactId>
    <version>1.4.1</version>
</dependency>
<dependency>
    <groupId>org.apache.maven.resolver</groupId>
    <artifactId>maven-resolver-transport-http</artifactId>
    <version>1.4.1</version>
</dependency>
退出移动版