首页 文章

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

提问于
浏览
73

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

  • 能够将系统属性传递给可执行Java代码

  • 能够将命令行参数传递给可执行Java代码

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

我找到了另外两个SO帖子,通过Gradle解决Java程序执行:one with an answer that advocates using apply plugin: "application" in the build file and gradle run at the command lineanother with answers advocating that approach as well as using task execute(type:JavaExec) in the build file and gradle execute at the command line . 我尝试了两种方法,但没有成功 .

我有两个问题:

(1) I cannot get the Java executable to read the system properties

我是否这样做:

build.gradle

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

Command line

gradle run -Dmyproperty=myvalue

或这个:

build.gradle

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

Command line

gradle execute -Dmyproperty=myvalue

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

(2) I cannot pass command line arguments

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

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

4 回答

  • 1

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

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

    似乎 javaExec 和应用程序插件方法都是有效的 . 如果想要使用其他一些功能(自动组合分发等),人们可能会喜欢应用程序插件方法

    以下是解决方案:

    JavaExec方法

    Command Line

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

    应用程序插件方法

    Command Line

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

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

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

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

  • 111

    我是新手,所以我需要这个,并且使用gradle 4.6为我工作的东西对命令行来说似乎更容易一些 . 你可以传递一个args数组,而不是解析1个arg字符串,我找到了一种传递所有属性的方法 . 合并如下:

    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=
    
  • 0

    也许我迟到了,但有没有人试过“在执行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 不能分期;或者只将第一期之前的部分作为关键 .

相关问题