当前位置:
首页
文章
后端
详情

要如何获取Maven项目的版本号?详解三种获取方式

Maven 是经常用来创建项目的一个工具,主要是因为它方便项目构建、管理以及下载 jar 包。那么,如果我们想知道所使用的 Maven 的版本号是多少,要怎么实现呢?下面我将为大家详细介绍三种获取 Maven 版本号的方式以及具体操作方法。

目前大多数Spring Boot项目都会打成Jar包,所以什么War包、Ear包的就先不摸索了。

Jar包的秘密

我们先解压一个Spring Boot应用Jar包看看里面能不能找到一些蛛丝马迹。在META-INF文件夹中找到了两个相关的东西,一个是MANIFEST.MF:

Manifest-Version: 1.0
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Implementation-Title: spring-boot-version
Implementation-Version: 1.0.23
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
Start-Class: cn.felord.SpringBootVersionApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 2.4.5
Created-By: Maven Jar Plugin 3.2.0
Main-Class: org.springframework.boot.loader.JarLauncher

里面包含了我定义的版本号1.0.23,Implementation-Version这个值好像通过代码能够获得:

String version = this.getClass().getPackage().getImplementationVersion()

但是用IDE启动发现version=null,不过用java -jar运行时version = 1.0.23。可能与IDE运行并不是通过jar的方式有关。

另一个是pom.properties,Maven项目编译会生成一个Properties配置文件:

artifactId=spring-boot-version
groupId=cn.felord
version=1.0.23

这岂不是读取Properties文件就可以了?

  String path = "META-INF/maven/cn.felord/spring-boot-version/pom.properties";
  ClassPathResource resource = new ClassPathResource(path);

  InputStream inputStream = resource.getInputStream();
  try (InputStreamReader reader = new InputStreamReader(inputStream)) {
      try (BufferedReader bufferedReader = new BufferedReader(reader)) {
          bufferedReader.lines()
                                .forEach(System.out::println);
         }
     } catch (Exception ignored) {

  }

这岂不是读取Properties文件就可以了?

  String path = "META-INF/maven/cn.felord/spring-boot-version/pom.properties";
  ClassPathResource resource = new ClassPathResource(path);

  InputStream inputStream = resource.getInputStream();
  try (InputStreamReader reader = new InputStreamReader(inputStream)) {
      try (BufferedReader bufferedReader = new BufferedReader(reader)) {
          bufferedReader.lines()
                                .forEach(System.out::println);
         }
     } catch (Exception ignored) {

  }

依然只能从jar读取,而且比较麻烦。这两种方式都要依赖jar包,有木有不单纯依赖jar包的呢?

Maven资源插件过滤

Maven在构建项目时可以通过资源插件将构建属性即pom.xml中的属性注入到指定的资源文件中,具体操作为:

<build>
  ...
  <resources>
    <!-- include main.properties -->
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
      <includes>
        <include>main.properties</include>
      </includes>
    </resource>
  </resources>
  ...
</build>

恰好spring-boot-starter-parent中已经设置了这种方式。

      <resource>
        <directory>${basedir}/src/main/resources</directory>
        <filtering>true</filtering>
        <includes>
          <include>**/application*.yml</include>
          <include>**/application*.yaml</include>
          <include>**/application*.properties</include>
        </includes>
      </resource>

如果你是application.properties,你可以通过下面的方式来接收版本号:

application.version = ${project.version}

如果是application.yaml,你可以通过下面的方式来接收版本号:

application:
  version: '@project.version@'

然后如何取值就不用多说了吧。这种方式不依赖jar包,使用起来也很简单。

Spring Boot提供

Spring Boot其实已经内置了获取项目构建信息的自动配置ProjectInfoAutoConfiguration,它包含一个条件BeanBuildProperties:

    @ConditionalOnResource(
        resources = {"${spring.info.build.location:classpath:META-INF/build-info.properties}"}
    )
    @ConditionalOnMissingBean
    @Bean
    public BuildProperties buildProperties() throws Exception {
        return new BuildProperties(this.loadFrom(this.properties
                                                 .getBuild()
                                                 .getLocation(), "build",                                                     this.properties
                                                 .getBuild().getEncoding()));
    }

这个BuildProperties提供了不少构建信息:

public class BuildProperties extends InfoProperties {
    public BuildProperties(Properties entries) {
        super(processEntries(entries));
    }

    public String getGroup() {
        return this.get("group");
    }

    public String getArtifact() {
        return this.get("artifact");
    }

    public String getName() {
        return this.get("name");
    }

    public String getVersion() {
        return this.get("version");
    }

    public Instant getTime() {
        return this.getInstant("time");
    }
   } 

其中的条件build-info.properties可以通过Spring Boot插件spring-boot-maven-plugin执行下面的命令生成:

mvn spring-boot:build-info

我们只需要配置插件为:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>
                    build-info
                </goal>
            </goals>
        </execution>
    </executions>
</plugin>

就能使得BuildProperties生效,我们可以轻松取得相关的信息:

{
  "version" : "1.0.23",
  "group" : "cn.felord",
  "artifact" : "spring-boot-version",
  "name" : "spring-boot-version",
  "time" : {
    "epochSecond" : 1620664643,
    "nano" : 591000000
  }
}

总结

今天介绍了几种从通过API获取项目构建版本信息的方法,有什么用呢?主要用于项目监控,发版审计,DevOps等领域,包括Spring Boot的自定义banner。如果你的项目涉及到CI/CD,很可能要涉及到这一方面。 如果你知道更好用的获取方法欢迎留言讨论,我来抛砖引玉。

以上就是关于三种获取 Java Maven 的版本号方式的详细内容,想要了解更多关于 Java Maven 项目的其他资料请关注W3Cschool其它相关文章!也希望大家能够多多支持我们!


免责申明:本站发布的内容(图片、视频和文字)以转载和分享为主,文章观点不代表本站立场,如涉及侵权请联系站长邮箱:xbc-online@qq.com进行反馈,一经查实,将立刻删除涉嫌侵权内容。

同类热门文章

深入了解C++中的new操作符:使用具体实例学习

C++中的new操作符是动态分配内存的主要手段之一。在程序运行时,我们可能需要动态地创建和销毁对象,而new就是为此提供了便利。但是,使用new也常常会引发一些问题,如内存泄漏、空指针等等。因此,本文将通过具体的示例,深入介绍C++中的new操作符,帮助读者更好地掌握其使用。


深入了解C++中的new操作符:使用具体实例学习

怎么用Java反射获取包下所有类? 详细代码实例操作

Java的反射机制就是在运行状态下,对于任何一个类,它能知道这个类的所有属性和方法;对于任何一个对象,都能调用这个对象的任意一个方法。本篇文章将通过具体的代码示例,展示如何通过Java反射来获取包下的所有类。


怎么用Java反射获取包下所有类? 详细代码实例操作

了解Java中的volati关键字的作用 以及具体使用方法

本篇文章将和大家分享一下Java当中的volatile关键字,下面将为各位小伙伴讲述volatile关键字的作用以及它的具体使用方法。


了解Java中的volati关键字的作用 以及具体使用方法

Java Map 所有的值转为String类型

可以使用 Java 8 中的 Map.replaceAll() 方法将所有的值转为 String 类型: 上面的代码会将 map 中所有的值都转为 String 类型。 HashMap 是 Java

Java Map 所有的值转为String类型

员工线上学习考试系统

有点播,直播,在线支付,三级分销等功能,可以对学员学习情况的监督监控,有源码,可二次开发。支持外网和局域网私有化部署,经过测试源码完整可用!1、视频点播:视频播放,图文资料,课件下载,章节试学,限时免

员工线上学习考试系统