在运行时获取Maven工件版本

我注意到,在Maven工件的JAR中,project.version属性包含在两个文件中:

META-INF/maven/${groupId}/${artifactId}/pom.properties META-INF/maven/${groupId}/${artifactId}/pom.xml 

有没有推荐的方式来阅读这个版本在运行时?

您不需要访问Maven特定的文件来获取任何给定的库/类的版本信息。

您可以简单地使用getClass().getPackage().getImplementationVersion()来获取存储在.jar-files MANIFEST.MF的版本信息。 幸运的是,Maven足够聪明不幸的是,Maven并没有将正确的信息写入清单中。

相反,必须修改maven-jar-plugin<archive>configuration元素来设置addDefaultImplementationEntriesaddDefaultSpecificationEntriestrue ,如下所示:

 <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifest> <addDefaultImplementationEntries>true</addDefaultImplementationEntries> <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> </manifest> </archive> </configuration> </plugin> 

理想的情况下,这个configuration应该被放入公司或其他基地。

有关<archive>元素的详细文档可以在Maven Archive文档中find 。

为了跟上上面的答案,对于一个.war神器,我发现我必须将等价的configuration应用到maven-war-plugin ,而不是maven-jar-plugin

 <plugin> <artifactId>maven-war-plugin</artifactId> <version>2.1</version> <configuration> <archive> <manifest> <addDefaultImplementationEntries>true</addDefaultImplementationEntries> <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> </manifest> </archive> <archiveClasses>true</archiveClasses> </configuration> </plugin> 

这将版本信息添加到项目的.jar (包含在.war WEB-INF/lib中)的MANIFEST.MF中,

这里有一个从pom.properties获取版本的方法,可以从清单中获取

 public synchronized String getVersion() { String version = null; // try to load from maven properties first try { Properties p = new Properties(); InputStream is = getClass().getResourceAsStream("/META-INF/maven/com.my.group/my-artefact/pom.properties"); if (is != null) { p.load(is); version = p.getProperty("version", ""); } } catch (Exception e) { // ignore } // fallback to using Java API if (version == null) { Package aPackage = getClass().getPackage(); if (aPackage != null) { version = aPackage.getImplementationVersion(); if (version == null) { version = aPackage.getSpecificationVersion(); } } } if (version == null) { // we could not compute the version so use a blank version = ""; } return version; } 

我花了一些时间在这里的两个主要方法,他们没有为我工作。 我正在使用Netbeans进行构build,可能还有更多。 我有一些错误和警告Maven 3的一些结构,但我认为这些很容易纠正。 没什么大不了

在DZone的这篇文章中,我find了一个可以维护和简单实现的答案:

  • 使用Maven在属性文件中标记版本号和生成时间

我已经有一个资源/configuration子文件夹,我命名我的文件:app.properties,以更好地反映我们可能保留在那里(如支持URL等)的types。

唯一的警告是Netbeans给出了一个警告,说IDE需要过滤掉。 不知道在哪里/如何。 这一点没有效果。 如果我需要穿越那座桥,也许有一个解决办法。 祝你好运。

为了在Eclipse中以及在Maven构build中运行,您应该添加其他答复中所述的addDefaultImplementationEntriesaddDefaultSpecificationEntries pom条目,然后使用以下代码:

 public synchronized static final String getVersion() { // Try to get version number from pom.xml (available in Eclipse) try { String className = getClass().getName(); String classfileName = "/" + className.replace('.', '/') + ".class"; URL classfileResource = getClass().getResource(classfileName); if (classfileResource != null) { Path absolutePackagePath = Paths.get(classfileResource.toURI()) .getParent(); int packagePathSegments = className.length() - className.replace(".", "").length(); // Remove package segments from path, plus two more levels // for "target/classes", which is the standard location for // classes in Eclipse. Path path = absolutePackagePath; for (int i = 0, segmentsToRemove = packagePathSegments + 2; i < segmentsToRemove; i++) { path = path.getParent(); } Path pom = path.resolve("pom.xml"); try (InputStream is = Files.newInputStream(pom)) { Document doc = DocumentBuilderFactory.newInstance() .newDocumentBuilder().parse(is); doc.getDocumentElement().normalize(); String version = (String) XPathFactory.newInstance() .newXPath().compile("/project/version") .evaluate(doc, XPathConstants.STRING); if (version != null) { version = version.trim(); if (!version.isEmpty()) { return version; } } } } } catch (Exception e) { // Ignore } // Try to get version number from maven properties in jar's META-INF try (InputStream is = getClass() .getResourceAsStream("/META-INF/maven/" + MAVEN_PACKAGE + "/" + MAVEN_ARTIFACT + "/pom.properties")) { if (is != null) { Properties p = new Properties(); p.load(is); String version = p.getProperty("version", "").trim(); if (!version.isEmpty()) { return version; } } } catch (Exception e) { // Ignore } // Fallback to using Java API to get version from MANIFEST.MF String version = null; Package pkg = getClass().getPackage(); if (pkg != null) { version = pkg.getImplementationVersion(); if (version == null) { version = pkg.getSpecificationVersion(); } } version = version == null ? "" : version.trim(); return version.isEmpty() ? "unknown" : version; } 

如果您的Java构build将目标类放在“target / classes”之外的某个位置,那么您可能需要调整segmentsToRemove的值。

我正在使用maven-assembly-plugin作为我的maven包装。 在Joachim Sauer的答案中使用Apache Maven Archiver也可以工作:

 <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <addDefaultImplementationEntries>true</addDefaultImplementationEntries> <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> </manifest> </archive> </configuration> <executions> <execution .../> </executions> </plugin> 

因为archiever是Maven共享组件之一 ,所以它可以被多个Maven构build插件使用,如果引入了两个或多个插件(包括archiveconfiguration),也可能会有冲突。