Java 如何从引导运行传递JVM选项
我正在开发一个简单的SpringWeb应用程序,它可以与远程主机进行通信,我想在公司代理之后对它进行本地测试。 我使用“Spring Boot”gradle插件,问题是如何为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=
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”
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