如果有个需求是要通过代码调用 maven 命令,来上传 jar 包或进行其他操作,该如何实现?
调用命令行当然可以,maven 官方也有一个项目 Apache Maven Invoker 实现类似需求,但前提是服务运行的机器或者容器中需要有 maven。
大家可能都听说过 Write once, run anywhere. 如果没了 maven 环境就执行不了了,有没有更好的方式呢
Maven Embedder 也是 maven 官方的一个项目,如名字一样,是可嵌入的,也就是不需要依赖外部 maven。项目是个好项目,但问题就是官方提供的文档实在太少了。
以防被喷,这里没有说嵌入一定是更好的方案,毕竟不可能把项目所需的所有依赖都打包到一起,还是要根据实际问题来选择的。
依赖
按照官方其实只需要 maven-embedder
一个依赖就可以,但实际运行起来,会发现报很多错,这里也不啰嗦,直接放出完整可用的依赖。
org.apache.maven
maven-embedder
3.6.3
org.apache.maven
maven-compat
3.6.3
org.apache.maven.resolver
maven-resolver-connector-basic
1.4.1
org.apache.maven.resolver
maven-resolver-transport-http
1.4.1
maven-compat
是一个用于保持与 Maven2 兼容性的包。
maven-resolver-connector-basic
和 maven-resolver-transport-http
用于 deploy。如果只运行到 install,不需要 deploy ,这两个依赖可以去掉。网上很多会用 aether 项目中的依赖,类似下面这种的
org.eclipse.aether
aether-connector-basic
1.0.2.v20150114
org.eclipse.aether
aether-transport-wagon
1.0.2.v20150114
但是实际上 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 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 的兼容包,但是还没找到其他的可替代品。
org.apache.maven
maven-compat
3.6.3
No connector factories available、No transporter factories registered
这两个都是部署过程中会报出的错误,添加如下依赖即可解决
org.apache.maven.resolver
maven-resolver-connector-basic
1.4.1
org.apache.maven.resolver
maven-resolver-transport-http
1.4.1