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


82

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

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

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

我发现了另外两个SO帖子,它们通过Gradle解决了Java程序的执行:一个在提倡apply plugin: "application"在构建文件中和gradle run命令行中使用的答案task execute(type:JavaExec)gradle execute另一个在提倡在构建文件中以及构建文件中使用该方法的答案。命令行。我尝试了两种方法,但都没有成功。

我有两个问题:

(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

无论哪种情况,myproperty都无法通过。从开始运行的代码MyMain.main (...)myproperty系统属性读取为null / missing。

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

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

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

Answers:


123

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

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

似乎javaExec和应用程序插件方法都是有效的。如果一个人想要使用其某些其他功能(自动组合发行版等),则可能会偏爱应用程序插件方法。

以下是解决方案:

JavaExec方法

命令行

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()    
}

3
我认为应该是System.getProperties()(大写S)。
orlanthi 2014年

1
如果您使用的是Gradle 2.xx,则还可以使用以下代码:systemProperty "myvariable", "${myvariable}"
eadjei 2014年

1
谢谢!我放的是试图运行Cucumber测试,并想将环境变量传递给JVM。我只是将“ systemProperties System.getProperties()”放在测试{}中,而不是在运行{}中
Svante 2014年

1
请注意,默认分割不允许带有空格的参数,例如-Dexec.args="--greeting 'hello there'"–将不起作用,需要设置另一个定界符。
伊万·巴拉索夫

3
使用:args System.getProperty(“ exec.args”,“”).split()避免在未提供args的情况下出现空指针异常。例如,即使“gradle这个任务”将引发与建议的build.gradle一个例外
麦克Hanafey

12

对于那些可能不想通过传递不相关的Gradle道具来污染应用程序的系统属性的人,建议您对参数进行命名。

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

java ... -Dprefix.my.prop=true 将传递 my.prop


3

我是gradle的新手,所以我需要它,而gradle 4.6的工作对我来说似乎对命令行来说要容易一些。代替解析1个arg字符串,您可以传递一个args数组,而且我找到了一种也可以用一行来传递所有属性的方法。合并如下:

apply plugin: 'java'
apply plugin: 'org.springframework.boot'    <- for my project

task runApp(type: JavaExec) {
  classpath = sourceSets.main.runtimeClasspath

  main = 'testit.TomcatApp'

  // arguments to pass to the application
  //  args 'myarg1 -rest'    <- came in as 1 string

  args = ["--myarg1 with spaces even", "--myarg2"]

  // and to pass in all -D system property args:
  systemProperties = System.properties
}

gradle run -Dwhatever=xxx -Dmyarg2=hey

// Java reading them:
public static void main(String[] args) {
    for ( int i = 0; i < args.length; i++ )
        {
        logger.info( "** args [" + i + "] =" + args[i] + "=" );
        }
    logger.info( "** -Dwhatever =" + System.getProperty("whatever") + "=" );
    logger.info( "** -Dmyarg2 =" + System.getProperty("myarg2") + "=" );

[main] INFO testit.TomcatApp - ** args [0] =--myarg1 with spaces even=
[main] INFO testit.TomcatApp - ** args [1] =--myarg2=
[main] INFO testit.TomcatApp - ** -Dwhatever =xxx=
[main] INFO testit.TomcatApp - ** -Dmyarg2 =hey=

-2

也许我参加晚会很晚,但是有人尝试过“在执行gradle之前先设置好道具”吗?我已经测试过了,这显然也可行。

myVar=myVal gradle test

例如,您可以将活动配置文件设置为:

SPRING_PROFILES_ACTIVE=dev  gradle test

这些显然也可以工作:(经过测试)

set myVar=myVal && gradle test      # for windows
export myVar=myVal && gradle test   # for linux and mac

警惕myVar不能分开的时期;否则仅将第一个期间之前的部分作为关键。

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.