如果有个需要是要通过代码调用 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-basic
和 maven-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
时波及服务器的账户和明码,可能须要配置文件,这里有两种解决方案:
- 通过
-s,--settings
来指定配置文件的门路。 - 把配置文件放到 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>