Java 如何从引导运行传递JVM选项

Java 如何从引导运行传递JVM选项,java,gradle,spring-boot,Java,Gradle,Spring Boot,我正在开发一个简单的SpringWeb应用程序,它可以与远程主机进行通信,我想在公司代理之后对它进行本地测试。 我使用“Spring Boot”gradle插件,问题是如何为JVM指定代理设置? 我尝试了几种方法: gradle-Dhttp.proxyHost=X.X.X-Dhttp.proxyPort=8080 bootRun export JAVA_OPTS=“-Dhttp.proxyHost=X.X.X-Dhttp.proxyPort=8080” export GRADLE\u OPTS=

我正在开发一个简单的SpringWeb应用程序,它可以与远程主机进行通信,我想在公司代理之后对它进行本地测试。 我使用“Spring Boot”gradle插件,问题是如何为JVM指定代理设置?

我尝试了几种方法:

  • gradle-Dhttp.proxyHost=X.X.X-Dhttp.proxyPort=8080 bootRun
  • export JAVA_OPTS=“-Dhttp.proxyHost=X.X.X-Dhttp.proxyPort=8080”
  • export GRADLE\u OPTS=“-Dhttp.proxyHost=X.X.X-Dhttp.proxyPort=8080”
  • 但它们似乎都不起作用——“NoRouteToHostException”抛出了“网络”代码。 此外,我还添加了一些额外的代码来调试JVM开始参数:

        RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
        List<String> arguments = runtimeMxBean.getInputArguments();
        for (String arg: arguments) System.out.println(arg);
    

    一切都很好

    在gradle构建脚本中,定义运行任务的系统属性

    //to provide the properties while running the application using spring-boot's run task
        run {
            systemProperties['property name'] = 'value'
        }
    
    gradle run
    应接受此值

    或定义项目级属性,如中所述 原始答案(使用Gradle 1.12和Spring Boot 1.0.x):

    SpringBootGradle插件的
    bootRun
    任务扩展了GradleJavaExec任务。看

    这意味着您可以通过添加以下内容将插件配置为使用代理:

    bootRun {
       jvmArgs = "-Dhttp.proxyHost=xxxxxx", "-Dhttp.proxyPort=xxxxxx"
    }
    
    到您的生成文件

    当然,您可以使用
    systemProperties
    而不是
    jvmArgs

    如果要从命令行有条件地添加JVMARG,可以执行以下操作:

    bootRun {
        if ( project.hasProperty('jvmArgs') ) {
            jvmArgs project.jvmArgs.split('\\s+')
        }
    }
    
    gradle bootRun -PjvmArgs="-Dwhatever1=value1 -Dwhatever2=value2"
    
    更新答案:

    在使用Spring Boot 1.2.6.RELEASE和Gradle 2.7试用了上述解决方案之后,我发现它没有像一些评论所提到的那样工作。 但是,可以进行一些小的调整来恢复工作状态

    新守则是:

    bootRun {
       jvmArgs = ["-Dhttp.proxyHost=xxxxxx", "-Dhttp.proxyPort=xxxxxx"]
    }
    
    对于硬编码参数,以及

    bootRun {
        if ( project.hasProperty('jvmArgs') ) {
            jvmArgs = (project.jvmArgs.split("\\s+") as List)
    
        }
    }
    
    对于从命令行提供的参数,它似乎可以工作:

    bootRun {
        systemProperties "property1": "value1", "property2": "value2"
    }
    
    这会将所有JVM选项传递给通过
    bootRun
    启动的应用程序

    bootRun {
      args = ['myProgramArgument1', 'myProgramArgument2']
    }
    

    使用jvmArgs可能会导致JVM启动问题。使用args可以传递自定义程序参数

    @marvin,感谢您的帖子,这非常有帮助

    分享我是如何使用它的:

    test {
      // support passing -Dsystem.property=value to bootRun task
      systemProperties = System.properties
    }
    
    我想跳过JUnit测试,除非使用属性包含此类测试。使用JUnit Aspect有条件地包括测试:

    //first line of test
    assumeThat(Boolean.parseBoolean(System.getProperty("deep.test.run","false"),true)
    
    使用gradle执行此操作需要在运行gradle build时提供系统属性,如图所示

    gradle build -Ddeep.test.run=true
    
    确实通过了测试


    希望这能帮助其他人尝试这种有条件地运行测试的方法。

    我遇到了类似的问题,bootRun需要一些参数,但我不想修改bootRun,因为我想保持一些灵活性并坚持标准的bootRun行为。我的建议是添加一些扩展bootRun的自定义任务(比如bootRunDev、bootRunProxy),如下面的代码段所述

    task bootRunPxy(type: org.springframework.boot.gradle.run.BootRunTask, dependsOn: 'build') {
        group = 'Application'
        doFirst() {
            main = project.mainClassName
            classpath = sourceSets.main.runtimeClasspath
            systemProperty 'http.proxyHost', 'xxxxx'
            systemProperty 'http.proxyPort', 'yyyyy'
        }
    }
    
    我没有一个环境来练习脚本,但我使用这种方法使用属性spring.profiles.active将概要文件传递给spring。
    值得一提的是,一些使用Gradle和Spring Boot的系统在
    build.Gradle
    之外启动JVM,例如在Dockerfile中

    在一个专门关于
    bootRun
    的线程中提到这一点并不是毫无意义的!我在这里结束是因为这篇文章吸引了人们在gradle下编译/运行的Spring Boot应用程序上下文中搜索jvm选项。(我找到的关于添加java.net.http.httpclient日志的所有建议都是“将它添加到
    bootRun
    jvmArgs
    ”。但是什么也没有发生

    因此,如果您碰巧从Docker容器运行gradle构建的Spring Boot应用程序,您将希望将JVM参数添加到项目Dockerfile中的env var,如下所示,例如-

    ...
    ENV JAVA_OPTS "${JAVA_OPTS} \
    -server \
    -Duser.timezone=UTC \
    -XX:InitialRAMPercentage=50 \
    -XX:MaxRAMPercentage=50 \
    -Djavax.net.ssl.trustStorePassword=elvislives \
    -Djavax.net.ssl.trustStoreProvider=BCFIPS \
    -Djavax.net.ssl.trustStoreType=BCFKS \
    -Djdk.internal.httpclient.debug=true \
    -Djava.util.logging.manager=org.apache.logging.log4j2.jul.LogManager \
    -Djdk.httpclient.HttpClient.log=errors,requests,headers,frames[:control:data:window:all..],content,ssl,trace,channel \
    "
    ...
    
    ENTRYPOINT java ${JAVA_OPTS} -cp app:app/lib/* com.mygreatcompany.theapp
    

    是的,这个解决方案是有效的。但是我不想让这段代码受源代码控制。我认为“最正确的”解决方案是直接在命令行中传递这个选项。有什么方法吗?文章中提到的链接有一种从命令行传递选项的方法。你能告诉我它与使用bootRun相比有什么不同吗?测试使用这个吗?类似的东西我不想让这个选项“硬编码”在生成文件中。最好能够指定代理设置。例如-使用命令行参数。不起作用:“>在根项目上找不到属性“args”。您是否正确复制了代码?我已进行了更新。没有
    args
    属性。我今天尝试过,唯一的方法是用方括号括住字符串列表,如bootRun{jvmArgs=[“-Dhttp.proxyHost=xxxxxx”,“-Dhttp.proxyPort=xxxxxx”}您使用的是哪个版本的gradle?这是目前为止将命令行选项传递给JVM@MarvinFromhold,谢谢你的回答。这种方法非常简单。对于像我这样的noob,如果你再添加一点细节,那将非常有用。建议:(1)显示带有参数的gradle命令行调用;(2)演示如何引用Spring Boot中的参数,例如,@Value(${property:default}”);(3)传递参数的IntelliJ对话框的屏幕截图也会很有帮助。遗憾的是,对我来说,仅仅添加这个参数就会导致gradle bootRun严重失败,出现“org.apache.catalina.LifecycleException:启动期间子容器失败”即使在没有传递任何-D参数的情况下,通过cherry选择我想要的属性作为答案,您能告诉我如何在Application.class或Bootstrap.class中使用这些参数吗?(我使用的是grails 3.x.x)我来这里也是出于同样的原因,因此感谢您发布此消息。但是,如何将此方法与
    gradle bootRun
    任务结合起来?我希望使用bootRun,以便容器也可以根据需要重建应用程序。
    task bootRunPxy(type: org.springframework.boot.gradle.run.BootRunTask, dependsOn: 'build') {
        group = 'Application'
        doFirst() {
            main = project.mainClassName
            classpath = sourceSets.main.runtimeClasspath
            systemProperty 'http.proxyHost', 'xxxxx'
            systemProperty 'http.proxyPort', 'yyyyy'
        }
    }
    
    ...
    ENV JAVA_OPTS "${JAVA_OPTS} \
    -server \
    -Duser.timezone=UTC \
    -XX:InitialRAMPercentage=50 \
    -XX:MaxRAMPercentage=50 \
    -Djavax.net.ssl.trustStorePassword=elvislives \
    -Djavax.net.ssl.trustStoreProvider=BCFIPS \
    -Djavax.net.ssl.trustStoreType=BCFKS \
    -Djdk.internal.httpclient.debug=true \
    -Djava.util.logging.manager=org.apache.logging.log4j2.jul.LogManager \
    -Djdk.httpclient.HttpClient.log=errors,requests,headers,frames[:control:data:window:all..],content,ssl,trace,channel \
    "
    ...
    
    ENTRYPOINT java ${JAVA_OPTS} -cp app:app/lib/* com.mygreatcompany.theapp