在代码中从maven的pom.xml中检索版本号的最简单方法是什么,即以编程方式?
当前回答
我在白天的工作中也遇到了同样的问题。尽管许多答案将有助于找到特定工件的版本,但我们需要获得不是应用程序直接依赖的模块/jar的版本。类路径在应用程序启动时由多个模块组装而成,主应用程序模块不知道后来添加了多少jar。
这就是为什么我提出了一个不同的解决方案,它可能比必须从jar文件中读取XML或属性更优雅一些。
这个想法
使用Java服务加载器方法可以在以后添加尽可能多的组件/构件,这些组件/构件可以在运行时提供它们自己的版本。创建一个非常轻量级的库,只需几行代码来读取、查找、筛选和排序类路径上的所有工件版本。 创建一个maven源代码生成器插件,在编译时为每个模块生成服务实现,在每个jar中打包一个非常简单的服务。
解决方案
解决方案的第一部分是构件版本服务库,现在可以在github和MavenCentral上找到它。它涵盖了服务定义和在运行时获得工件版本的几种方法。
第二部分是artifact-version-maven-plugin,也可以在github和MavenCentral上找到。它用于为每个工件提供一个轻松的生成器来实现服务定义。
例子
获取所有带有坐标的模块
不再读取jar清单,只是一个简单的方法调用:
// iterate list of artifact dependencies
for (Artifact artifact : ArtifactVersionCollector.collectArtifacts()) {
// print simple artifact string example
System.out.println("artifact = " + artifact);
}
返回一组已排序的工件。要修改排序顺序,提供一个自定义比较器:
new ArtifactVersionCollector(Comparator.comparing(Artifact::getVersion)).collect();
这样,工件列表将按版本号排序返回。
找到一个特定的工件
ArtifactVersionCollector.findArtifact("de.westemeyer", "artifact-version-service");
获取特定工件的版本详细信息。
查找具有匹配groupId的工件
找到groupId de.westemeyer的所有工件(精确匹配):
ArtifactVersionCollector.findArtifactsByGroupId("de.westemeyer", true);
查找groupId以de.westemeyer开头的所有工件:
ArtifactVersionCollector.findArtifactsByGroupId("de.westemeyer", false);
按版本号排序结果:
new ArtifactVersionCollector(Comparator.comparing(Artifact::getVersion)).artifactsByGroupId("de.", false);
在工件列表上实现自定义操作
通过提供一个lambda,第一个例子可以像这样实现:
ArtifactVersionCollector.iterateArtifacts(a -> {
System.out.println(a);
return false;
});
安装
将这两个标记添加到所有pom.xml文件中,或者可能添加到公司的某个pom主文件中:
<build>
<plugins>
<plugin>
<groupId>de.westemeyer</groupId>
<artifactId>artifact-version-maven-plugin</artifactId>
<version>1.1.0</version>
<executions>
<execution>
<goals>
<goal>generate-service</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>de.westemeyer</groupId>
<artifactId>artifact-version-service</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
反馈
如果有人能尝试一下这个解决方案,那就太好了。如果能得到你认为解决方案是否符合你的需求的反馈,那就更好了。所以,如果你有任何建议、功能请求、问题,请不要犹豫,在任何github项目上添加一个新问题。
执照
所有的源代码都是开源的,甚至可以免费用于商业产品(MIT许可证)。
其他回答
有时,当编写与项目版本相关的脚本时,Maven命令行就足够了,例如,通过URL从存储库检索工件:
mvn help:evaluate -Dexpression=project.version -q -DforceStdout
使用的例子:
VERSION=$( mvn help:evaluate -Dexpression=project.version -q -DforceStdout )
ARTIFACT_ID=$( mvn help:evaluate -Dexpression=project.artifactId -q -DforceStdout )
GROUP_ID_URL=$( mvn help:evaluate -Dexpression=project.groupId -q -DforceStdout | sed -e 's#\.#/#g' )
curl -f -S -O http://REPO-URL/mvn-repos/${GROUP_ID_URL}/${ARTIFACT_ID}/${VERSION}/${ARTIFACT_ID}-${VERSION}.jar
打包的工件包含META-INF/maven/${groupId}/${artifactId}/pom。属性文件,内容如下:
#Generated by Maven
#Sun Feb 21 23:38:24 GMT 2010
version=2.5
groupId=commons-lang
artifactId=commons-lang
许多应用程序使用这个文件在运行时读取应用程序/jar版本,不需要任何设置。
上述方法的唯一问题是,该文件(目前)是在包阶段生成的,因此在测试期间不会出现(有一个Jira问题可以改变这一点,请参阅MJAR-76)。如果这对您来说是一个问题,那么Alex描述的方法就是正确的方法。
公认的答案可能是将版本号静态地放入应用程序的最佳和最稳定的方法,但实际上并没有回答最初的问题:如何从pom.xml检索工件的版本号?因此,我想提供一个替代方案,展示如何在运行时动态地做这件事:
您可以使用Maven本身。更确切地说,您可以使用Maven库。
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
<version>3.3.9</version>
</dependency>
然后在Java中这样做:
package de.scrum_master.app;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import java.io.FileReader;
import java.io.IOException;
public class Application {
public static void main(String[] args) throws IOException, XmlPullParserException {
MavenXpp3Reader reader = new MavenXpp3Reader();
Model model = reader.read(new FileReader("pom.xml"));
System.out.println(model.getId());
System.out.println(model.getGroupId());
System.out.println(model.getArtifactId());
System.out.println(model.getVersion());
}
}
控制台日志如下:
de.scrum-master.stackoverflow:my-artifact:jar:1.0-SNAPSHOT
de.scrum-master.stackoverflow
my-artifact
1.0-SNAPSHOT
更新2017-10-31:为了回答Simon Sobisch的后续问题,我修改了这个例子:
package de.scrum_master.app;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Application {
public static void main(String[] args) throws IOException, XmlPullParserException {
MavenXpp3Reader reader = new MavenXpp3Reader();
Model model;
if ((new File("pom.xml")).exists())
model = reader.read(new FileReader("pom.xml"));
else
model = reader.read(
new InputStreamReader(
Application.class.getResourceAsStream(
"/META-INF/maven/de.scrum-master.stackoverflow/aspectj-introduce-method/pom.xml"
)
)
);
System.out.println(model.getId());
System.out.println(model.getGroupId());
System.out.println(model.getArtifactId());
System.out.println(model.getVersion());
}
}
还有一种方法描述了使用Maven显示你的应用版本号:
将此添加到pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>test.App</mainClass>
<addDefaultImplementationEntries>
true
</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
然后用这个:
App.class.getPackage().getImplementationVersion()
我发现这个方法更简单。
为了补充@kieste所发布的内容,我认为如果使用Spring-boot,这是在代码中提供Maven构建信息的最佳方式:http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#production-ready-application-info上的文档非常有用。
您只需要激活执行器,并在应用程序中添加所需的属性。属性或application.yml
Automatic property expansion using Maven
You can automatically expand info properties from the Maven project using resource filtering. If you use the spring-boot-starter-parent you can then refer to your Maven ‘project properties’ via @..@ placeholders, e.g.
project.artifactId=myproject
project.name=Demo
project.version=X.X.X.X
project.description=Demo project for info endpoint
info.build.artifact=@project.artifactId@
info.build.name=@project.name@
info.build.description=@project.description@
info.build.version=@project.version@
推荐文章
- JavaBean和POJO之间的区别是什么?
- 注释在Java中如何使用,在哪里使用?
- 如何在Ubuntu下安装JDK 11 ?
- Spring Boot -无法确定数据库类型为NONE的嵌入式数据库驱动程序类
- 如何转换/解析从字符串到字符在java?
- Java编译器级别与安装的Java项目facet的版本不匹配
- 如何在Android中动态更改菜单项文本
- 如何比较两个没有时间部分的日期?
- 如何在Java中找到给定类的所有子类?
- 匿名类的访问构造函数
- 从Java访问Kotlin扩展函数
- 解析LocalDateTime时无法从TemporalAccessor获取LocalDateTime (Java 8)
- 以AM/PM的12小时格式显示当前时间
- 求两个集合的差值
- Junit @Rule如何工作?