如何从 gradle 构建中获取版本属性以包含在运行时 Swing 应用程序中

问题描述 投票:0回答:7

我有一个简单的父项目,其中包含模块/应用程序。我选择的构建工具是 gradle。父级

build.gradle
定义如下。

apply plugin: 'groovy'
dependencies {
    compile gradleApi()
    compile localGroovy()
}


allprojects {
    repositories {
        mavenCentral()
    }

    version "0.1.0-SNAPSHOT"
}

我想做的是在我的 swing 应用程序中利用版本属性 (0.1.0-SNAPSHOT)。具体来说,我希望它显示在主 JFrame 的标题栏中。我希望能够做类似的事情

this.setTitle("My Application - v." + ???.version);

该应用程序是一个普通的java项目,但我不反对添加groovy支持,它会有所帮助。

java swing groovy gradle
7个回答
48
投票

我喜欢在构建过程中创建属性文件。这是直接从 Gradle 执行此操作的方法:

task createProperties(dependsOn: processResources) {
  doLast {
    new File("$buildDir/resources/main/version.properties").withWriter { w ->
        Properties p = new Properties()
        p['version'] = project.version.toString()
        p.store w, null
    }
  }
}

classes {
    dependsOn createProperties
}

24
投票

您始终可以按照某人的建议使用暴力并在构建过程中生成属性文件。更优雅的答案(仅部分有效)是使用

getClass().getPackage().getImplementationVersion()

问题是,只有当您从生成的 jar 运行应用程序时,这才有效 - 如果您直接从 IDE/扩展类运行它,上面的 getPackage 将返回 null。对于许多情况来说它已经足够好了 - 如果您从 IDE 运行(获取空包)并且适用于实际的客户端部署,则只需显示“DEVELOPMENT”。


12
投票

更好的主意是将项目版本保留在

gradle.properties
文件中。该文件中的所有属性将自动加载并可以在
build.gradle
脚本中使用。

然后,如果您在 swing 应用程序中需要该版本,请在

version.properties
文件夹下添加一个
src/main/resources
文件,并在应用程序构建期间过滤此文件,here 是一篇展示如何完成此操作的帖子。

version.properties
将包含在最终的 jar 中,因此可以通过
ClassLoader
读取和使用,并且可以在应用程序中显示该文件的属性。


4
投票

@Craig Trader 的更简单和更新的解决方案(适用于 Gradle 4.0/5.0)

task createProperties {
    doLast {
        def version = project.version.toString()
        def file = new File("$buildDir/resources/main/version.txt")
        file.write(version)
    }
}

war {
    dependsOn createProperties
}

1
投票

我使用了@Craig Trader的答案,但必须添加相当多的更改才能使其工作(它还添加了git详细信息):

task createProperties() {
    doLast {
        def details = versionDetails()
        new File("$buildDir/resources/main/version.properties").withWriter { w ->
            Properties p = new Properties()
            p['version'] = project.version.toString()
            p['gitLastTag'] = details.lastTag
            p['gitCommitDistance'] = details.commitDistance.toString()
            p['gitHash'] = details.gitHash.toString()
            p['gitHashFull'] = details.gitHashFull.toString() // full 40-character Git commit hash
            p['gitBranchName'] = details.branchName // is null if the repository in detached HEAD mode
            p['gitIsCleanTag'] = details.isCleanTag.toString()
            p.store w, null
        }
        // copy needed, otherwise the bean VersionController can't load the file at startup when running complete-app tests.
        copy {
            from "$buildDir/resources/main/version.properties"
            into "bin/main/"
        }
    }
}
classes {
    dependsOn createProperties
}

并从类的构造函数中加载它:VersionController

import static net.logstash.logback.argument.StructuredArguments.v;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.info.BuildProperties;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

@RestController
public class VersionController {

    final static Logger log = LoggerFactory.getLogger(AppInfoController.class);

    private Properties versionProperties = new Properties();

    private String gitLastTag;
    private String gitHash;
    private String gitBranchName;
    private String gitIsCleanTag;

    VersionController()
    {
        String AllGitVersionProperties = "";
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream("classpath:/version.properties");

        if(inputStream == null)
        {
            // When running unit tests, no jar is built, so we load a copy of the file that we saved during build.gradle.
            // Possibly this also is the case during debugging, therefore we save in bin/main instead of bin/test.
            try {
                inputStream = new FileInputStream("bin/main/version.properties");
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        try {
            versionProperties.load(inputStream);
        } catch (IOException e) {
            AllGitVersionProperties += e.getMessage()+":";
            log.error("Could not load classpath:/version.properties",e);
        }

        gitLastTag = versionProperties.getProperty("gitLastTag","last-tag-not-found");
        gitHash = versionProperties.getProperty("gitHash","git-hash-not-found");
        gitBranchName = versionProperties.getProperty("gitBranchName","git-branch-name-not-found");
        gitIsCleanTag = versionProperties.getProperty("gitIsCleanTag","git-isCleanTag-not-found");

        Set<Map.Entry<Object, Object>> mainPropertiesSet = versionProperties.entrySet();
        for(Map.Entry oneEntry : mainPropertiesSet){
            AllGitVersionProperties += "+" + oneEntry.getKey()+":"+oneEntry.getValue();
        }
         log.info("All Git Version-Properties:",v("GitVersionProperties", AllGitVersionProperties));
    }
}

0
投票

使用@Craig Trader的解决方案将属性保存在version.properties文件中。添加到build.gradle:

task createProperties() {
    doLast {
        def details = versionDetails()
        new File("$buildDir/resources/main/version.properties").withWriter { w ->
            Properties p = new Properties()
            p['version'] = project.version.toString()
            p['gitLastTag'] = details.lastTag
            p['gitCommitDistance'] = details.commitDistance.toString()
            p['gitHash'] = details.gitHash.toString()
            p['gitHashFull'] = details.gitHashFull.toString() // full 40-character Git commit hash
            p['gitBranchName'] = details.branchName // is null if the repository in detached HEAD mode
            p['gitIsCleanTag'] = details.isCleanTag.toString()
            p.store w, null
        }
        // copy needed, otherwise the bean VersionController can't load the file at startup when running complete-app tests.
        copy {
            from "$buildDir/resources/main/version.properties"
            into "bin/main/"
        }
    }
}
classes {
    dependsOn createProperties
}

要在 version.properties 中加载属性运行时,您需要使用

@PropertySource({"classpath:version.properties"})
注释您的类 然后,您可以将属性分配给带有注释的私有变量,例如:

@Value("${gitLastTag}")
private String gitLastTag;

完整示例:

package com.versioncontroller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;

import javax.annotation.PostConstruct;

import java.util.Properties;

@PropertySource({"classpath:version.properties"})
public class VersionController {

    @Value("${gitLastTag}")
    private String gitLastTag;
    @Value("${gitHash}")
    private String gitHash;
    @Value("${gitBranchName}")
    private String gitBranchName;
    @Value("${gitIsCleanTag}")
    private String gitIsCleanTag;

    @PostConstruct  // properties are only set after the constructor has run
    private void logVersion(){

        // when called during the constructor, all values are null.
        System.out.println("All Git Version-Properties:");
        System.out.println("gitLastTag: " + gitLastTag),
        System.out.println("gitHash: " + gitHash),
        System.out.println("gitBranchName: " + gitBranchName),
        System.out.println("gitIsCleanTag: " + gitIsCleanTag));
    }
}

0
投票

与其他答案类似,可以通过生成属性文件来存储此信息,然后在运行时读取其内容来解决这个问题。但是,您还应该考虑以下事项:

  • 将属性文件放在您的包名称下,以避免与依赖项中的同名文件发生冲突
    (如果您正在构建具有依赖项的 JAR / Uber JAR,这主要是一个问题)
  • 定义 Gradle 任务 inputsoutputs,以便 Gradle 知道任务何时是最新的
  • 不要对路径进行硬编码
    "$buildDir/resources/main"
    ;相反,你可以使用
    sourceSets.main.output.resourcesDir

    (更干净的解决方案可能是使用自定义输出目录,如
    SourceSetOutput
    文档
    “使用生成的资源”部分所建议)
  • 如果您想让构建可重现,请避免使用
    java.util.Properties
    写入属性,因为它包含当前时间并且使用操作系统行分隔符(Windows 上为
    \r\n
    ,Linux 上为
    \n

您可以使用

WriteProperties
任务 来避免手动编写属性文件,隐式定义 inputsoutputs,并避免上述
java.util.Properties
问题。

这是使用 Gradle Kotlin DSL(适用于 Gradle 8.10)的示例,其中

com.example
作为包名称:

val createVersionProperties by tasks.registering(WriteProperties::class) {
    // Uses `map` instead of `get` here to allow Gradle to only evaluate it when needed
    val filePath = sourceSets.main.map {
        // Place property file under own package to avoid conflicts when library is
        // packaged as JAR with dependencies
        it.output.resourcesDir!!.resolve("com/example/version.properties")
    }
    destinationFile = filePath

    property("version", project.version.toString())
}
// Specify dependency to make sure the task is automatically executed when needed
tasks.classes {
    dependsOn(createVersionProperties)
}

以下是读取属性的方法:

Properties properties = new Properties();
// Alternatively, if the current class is in the same package, you can use
// `getResourceAsStream("version.properties")`
try (InputStream versionPropertiesStream = getClass().getResourceAsStream("/com/example/version.properties")) {
    if (versionPropertiesStream == null) {
        throw new IllegalStateException("Version properties file does not exist");
    }
    properties.load(new InputStreamReader(versionPropertiesStream, StandardCharsets.UTF_8));
}

String version = properties.getProperty("version");
// ... use the version
© www.soinside.com 2019 - 2024. All rights reserved.