从代码中的Maven pom.xml检索版本


255

从Maven的pom.xml中以代码方式(即以编程方式)检索版本号的最简单方法是什么?

Answers:


262

假设您使用的是Java,则可以

  1. .properties在(最常见的)src/main/resources目录中创建一个文件(但是在第4步中,您可以告诉它在其他位置查找)。

  2. .properties使用项目版本的标准Maven属性设置文件中某些属性的值: foo.bar=${project.version}

  3. 在你的Java代码,加载从属性文件从classpath中的资源的价值(谷歌如何做到这一点很多例子,但这里是对于初学者一个例子)。

  4. 在Maven中,启用资源过滤-这将导致Maven将文件复制到您的输出类中,并在该复制过程中转换资源,从而解释属性。您可以在此处找到一些信息但是您大多只是在pom中这样做:

    <内部版本>
      <资源>
        <资源>
          <directory> src / main / resources </ directory>
          <filtering> true </ filtering>
        </ resource>
      </ resources>   
    </ build>

您还可以使用其他标准属性,例如project.nameproject.description或什至放在pom <properties>等中的任意属性。资源过滤与Maven配置文件结合使用,可以在构建时为您提供可变的构建行为。当在运行时使用来指定配置文件时-PmyProfile,可以启用属性,这些属性随后可以显示在构建中。


2
我发现了一个代码,是没有任何变化的Maven配置。
温德尔

7
注意不要在上直接使用过滤src/main/resources,因为这可能会处理此目录中的所有文件,包括二进制文件。为了避免不可预测的行为,最好对src/main/resources-filtered目录进行过滤,如此处建议的那样。无论如何,谢谢你的这个绝招!
SiZiOUS

1
下面使用MavenXppReader来获取实际模型的答案非常有用,因为它不需要运行任何操作即可找到值。如果您需要在运行任何版本之前了解其版本,请查看以下答案;让gradle知道已签出的Maven项目的版本对我很有帮助,因此我可以事先知道输出jar的位置。
阿贾克斯

92

公认的答案可能是将版本号静态地输入到应用程序中的最佳,最稳定的方法,但实际上并没有回答原始的问题:如何从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());
  }
}

1
这几乎等同于我所用,并从日食开始时工作正常,但不从正常启动时packaged罐子(依赖类没有集成)和不工作时,与Maven具组件插件封装jar-with-dependencies我得到一个java.io.FileNotFoundException: pom.xml(它在最终的jar中META-INF/maven/my.package/myapp/pom.xml)-有什么提示如何解决呢?
西蒙·索比斯

1
我的解决方案旨在在开发环境中动态工作,例如,在从IDE或控制台启动的测试或工具中使用时。该问题的可接受答案显示了几种将版本号静态打包到工件中的方法。我完全不认为pom.xml完全可以在JAR中使用。不过,对您来说不错。也许您可以在打开文件阅读器时调整路径,并使其取决于类加载器的情况。我将不得不自己尝试。如果这没有帮助,请随时提出后续问题。
kriegaex

2
@SimonSobisch,您好,我刚刚更新了我的答案,以便向您展示如何做自己想做的事情。但是请注意,我只是快速又肮脏地做了一个事实,我并不特别喜欢嵌套构造函数的代码。
kriegaex

75

打包的工件包含一个META-INF/maven/${groupId}/${artifactId}/pom.properties内容如下的文件:

#Generated by Maven
#Sun Feb 21 23:38:24 GMT 2010
version=2.5
groupId=commons-lang
artifactId=commons-lang

许多应用程序在运行时使用此文件来读取应用程序/ jar版本,需要零设置。

上述方法的唯一问题是,该文件(当前)是在package阶段中生成的,因此在测试等过程中将不存在(有一个Jira问题来更改此文件,请参见MJAR-76)。如果这对您来说是个问题,那么Alex所描述的方法就是正确的选择。


10
人们在寻找一个例子读取性能,这个帖子越过几种方法- javablog.fr/...
chrismarx

43

简易方式中还介绍了使用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()

我发现这种方法更简单。


18
-1-这个解决方案对我不起作用;的价值getImplementationVersion()null。(Maven版本3.0.4)
Jesse Webb

7
取决于阶段...仅在打包工件时才有效,因此不适用于单元测试:-/
Wikier 2013年

2
对于.war工件,请记住使用maven-war-plugin代替maven-jar-plugin
cs_pupil

对我来说,这在Tomcat 8中确实有效,但在Tomcat 7中getImplementationVersion()无效(返回null)。
阿方索西川

18

如果使用罐子或战争之类的mvn包装,请使用:

getClass().getPackage().getImplementationVersion()

它在存档中读取生成的META-INF / MANIFEST.MF(设置为pom.xml的版本)的属性“ Implementation-Version”。


18

为了补充@kieste发布的内容,我认为这是在使用Spring-boot的情况下在代码中提供Maven构建信息的最佳方法:http ://docs.spring.io/spring-boot/中的文档docs / current / reference / htmlsingle /#production-ready-application-info非常有用。

您只需要激活执行器,然后在application.properties或中添加所需的属性即可。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@


3

在编写与项目版本相关的脚本时,有时使用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

1
    <build>
            <finalName>${project.artifactId}-${project.version}</finalName>
            <pluginManagement>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-war-plugin</artifactId>
                        <version>3.2.2</version>
                        <configuration>
                            <failOnMissingWebXml>false</failOnMissingWebXml>
                            <archive>
                                <manifest>
                                    <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                                    <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
                                </manifest>
                            </archive>
                        </configuration>
                    </plugin>
                 </plugins>
            </pluginManagement>
</build>

使用获取版本 this.getClass().getPackage().getImplementationVersion()

PS不要忘记添加:

<manifest>
    <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
    <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>

0

参考ketankk的答案

不幸的是,添加此代码使我的应用程序如何处理资源变得混乱:

<build>
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
    </resource>
  </resources>   
</build>

但是在maven-assemble-plugin的<manifest>标记中使用了这个技巧:

<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>

所以我能够使用

String version = getClass().getPackage().getImplementationVersion();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.