如何在代码中获取Java应用当前的版本号?
最近需要在项目中获取项目的版本号,最笨的方法莫过于硬编码一个版本号,当然我也是这么干的。不过闲下来的时候突发奇想Spring Boot项目中pom.xml
定义的版本号能不能通过API获得呢?于是利用摸鱼的时间研究了这种无聊透顶的东西。
❝目前大多数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
:
-
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) {
-
-
}
依然只能从jar读取,而且比较麻烦。这两种方式都要依赖jar包,有木有不单纯依赖jar包的呢?
从配置文件读取
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也可以使用。算是一个锦上添花的小Tips,简单了解一下就好。
文章来源: felord.blog.csdn.net,作者:码农小胖哥,版权归原作者所有,如需转载,请联系作者。
原文链接:felord.blog.csdn.net/article/details/116677801
- 点赞
- 收藏
- 关注作者
评论(0)