通过 Gradle 运行 Java 类时传递系统属性和参数时出现问题

2022-08-31 11:32:30

我正在尝试通过Gradle运行命令行Java应用程序,作为快速集成测试的一部分。我正在从Maven移植我的构建脚本,通过.我的两大要求是:exec-maven-plugin

  • 能够将系统属性传递给可执行的 Java 代码
  • 能够将命令行参数传递给可执行 Java 代码

请注意,我不是在尝试在构建脚本中读取这些属性,而是在脚本构建和执行的Java程序中读取它们。

我发现另外两篇SO文章通过Gradle解决了Java程序执行的问题:一篇是倡导使用apple插件的答案:构建文件中的“application”和在命令行运行的gradle,另一篇是提倡这种方法的答案,以及在构建文件中使用任务执行(type:JavaExec),并在命令行执行gradle。我尝试了这两种方法,但没有成功。

我有两个问题:

(1) 我无法获取 Java 可执行文件来读取系统属性

我是否这样做:

build.gradle

apply plugin: 'application'
mainClassName = "com.mycompany.MyMain"

命令行

gradle run -Dmyproperty=myvalue

或者这个:

build.gradle

task execute (type:JavaExec) {
    main = "com.mycompany.MyMain"
    classpath = sourceSets.main.runtimeClasspath 
}

命令行

gradle execute -Dmyproperty=myvalue

在任何一种情况下,都无法通过。从 开始运行的代码将系统属性读取为 null/missing。mypropertyMyMain.main (...)myproperty

(2) 我无法传递命令行参数

这可能与第一个问题有关。例如,在 中,命令行参数本身是通过系统属性传入的。Gradle 就是这种情况,还是有另一种方法可以传递命令行参数?exec-maven-plugin

如何通过这些变量?另外,是使用更好还是?apply plugin: 'application'task execute (type:JavaExec)


答案 1

想通了。主要问题是,当Gradle分叉一个新的Java进程时,它不会自动将环境变量值传递给新环境。必须通过任务或插件的属性显式传递这些变量。systemProperties

另一个问题是了解如何传递命令行参数;这些都是通过任务或插件上的属性。与 Maven 一样,它们应该通过另一个系统属性在命令行上传递,作为一个空格分隔的列表,然后需要在设置 之前,接受对象。我已经命名了物业,这是旧的Maven名字。argsexec-maven-pluginsplit()argsListexec.args

似乎和应用程序插件方法都是有效的。如果想要使用其其他一些功能(自动将发行版放在一起等),则可能会更喜欢应用程序插件方法。javaExec

以下是解决方案:

JavaExec Approach

命令行

gradle execute -Dmyvariable=myvalue -Dexec.args="arg1 arg2 arg3"

build.gradle

task execute (type:JavaExec) {

    main = "com.myCompany.MyMain"
    classpath = sourceSets.main.runtimeClasspath 

    /* Can pass all the properties: */
    systemProperties System.getProperties()

    /* Or just each by name: */
    systemProperty "myvariable", System.getProperty("myvariable")

    /* Need to split the space-delimited value in the exec.args */
    args System.getProperty("exec.args", "").split()    
}

应用程序插件方法

命令行

gradle run -Dmyvariable=myvalue -Dexec.args="arg1 arg2 arg3"

build.gradle

apply plugin: 'application'
mainClassName = "com.mycompany.MyMain"
run {    
    /* Can pass all the properties: */
    systemProperties System.getProperties()

    /* Or just each by name: */
    systemProperty "myvariable", System.getProperty("myvariable")

    /* Need to split the space-delimited value in the exec.args */
    args System.getProperty("exec.args", "").split()    
}

答案 2

对于那些可能不想通过传递不相关的 Gradle 道具来污染应用程序的系统属性的人,我建议将参数的命名空间设置为命名空间。

tasks.withType(JavaExec) {
    System.properties.each { k,v->
        if (k.startsWith("prefix.")) {
            systemProperty k - "prefix.", v
        }
    }
}

java ... -Dprefix.my.prop=true将通过my.prop


推荐