Gradle 不收集以 -D 开头的字符串
Posted
技术标签:
【中文标题】Gradle 不收集以 -D 开头的字符串【英文标题】:Gradle doesn't collect strings starting with -D 【发布时间】:2018-03-08 21:14:24 【问题描述】:这是 Gradle 还是 Groovy 错误?
我想将 JVM 参数从 Gradle 传递到分叉的 JVM,不幸的是这不是自动完成的。这应该可以工作,build.gradle
:
...
bootRun
jvmArgs = System.properties.iterator().findAllit.key.startsWith('myapp').collect
"-D$it.key=$it.value"
...
执行如下:
gradle bootRun -Dmyapp.port=34501 -Dmyapp.member.name=server1
如果字符串以-D
开头,方法collect
总是返回空集合。如果它以其他任何内容开头,则返回预期的两个元素字符串集合。如果我在-D
之前放置空间,它也可以工作,但是它会在:findMainClass
上进一步破坏下游的构建,并用主类名误解-Dmyapp.port=...
。它只需以-D
开头。
我也尝试了不同的字符串连接,但结果是一个以 -D 开头的字符串,它不起作用。
这是一个错误还是我遗漏了什么。这是我的第一个 Gradle 项目,我不是 Groovy 开发人员。 我应该报告错误吗?在哪里,Groovy 还是 Gradle?
注意事项: 我正在从 IntelliJ IDE 2016.1.2 运行 Gradle 使用 Gradle 3.5 Forked JVM 运行 Spring Boot 应用程序
更新 非常抱歉,我的错!事实上,JVM 参数是使用上面的公式传递下来的;问题在于我如何测量它不是。我只是把打印输出:
println "jvmArgs: $jvmArgs"
println "jvmArgs.size: $jvmArgs.size"
println "jvmArgs.class: $jvmArgs.class"
..如果jvmArgs.size == 0
,则中止bootRun,以避免应用程序启动缓慢;也就是说,我并没有真正检查应用程序本身是否传递了参数。事实证明他们是。
仅供参考,输出是:
jvmArgs: []
jvmArgs.size: 0
jvmArgs.class: java.lang.ArrayList
jvmArgs 类被报告为标准 ArrayList,但其行为更像 输入流使用者,无论 jvmArgs 分配给什么数组,都会扫描该数组以查找所有以“-D”开头的字符串,那些是消耗(被什么?),传递给一些 ProcessBuilder (??) 并且 jvmArgs 只剩下剩余的元素。
举个例子:
jvmArgs = ["-Daaa=bbb", "foo", "bar"]
jvmArgs = ["stuff", "-Dccc=ddd", "morestuff"]
jvmArgs = ["-Deee=fff"]
println "jvmArgs: $jvmArgs"
..它打印 jvmArgs: []
并且 Spring Boot 应用程序以 -Daaa=bbb -Dccc=ddd -Deee=fff
启动。
有人能解释一下是什么原因导致这个神奇的流类似于 jvmArgs 的属性,否则它声称是一个简单的 ListArray?
【问题讨论】:
这绝对不是一个错误——它早就被发现了。你如何运行gradle?从控制台,哪个外壳?或者可能来自 IDE。 你是对的,它一直有效,请阅读我的解释。奇怪的行为似乎是设计使然。 【参考方案1】:这对我有用,但我对观察到的行为没有解释。无论如何,希望它有所帮助。
def array = System.properties.iterator().findAll
it.key.startsWith('myapp')
.collect
"-D$it.key=$it.value"
jvmArgs.addAll(array)
编辑
jvmArgs = ["value"] 调用 setJvmArgs,如果我没有遗漏什么,它会从 JavaExec 转到 JavaExecHandleBuilder,然后是 JvmOptions。在这里,一些参数被删除。以 -D 开头的条目被添加到系统属性中。
setJvmArgs( ["-Dtest=1", "xx"])
println getJvmArgs() //[xx]
println systemProperties //[test:1]
您的应用程序是否无权访问这些属性?
https://github.com/gradle/gradle/blob/master/subprojects/core/src/main/java/org/gradle/process/internal/JvmOptions.java#L183
编辑:后台发生了什么
在 Groovy 中,属性赋值调用 setter,访问它会调用 getter。它们可以互换。如果您省略了 setter 和 getter 对,它将为您生成并在字节码中可见。但你甚至可以省略属性本身,只写 getter 和 setter 对并将其用作属性。
class Foo
def setBar(String foo) println "no thanks"
String getBar() "test"
f = new Foo()
f.bar="write Var" // println "no thanks"
println f.bar instanceof String // --> f.getBar() inst... true
println f.bar //
因此,您从未将 List 分配给变量,而是调用 setJvmArgs(List)。您可以使用 getAllJvmArgs() btw 列出所有参数。
结合委托策略和动态属性/方法,这可能是 DSL 编程的福音,但却是调试的祸根……
http://groovy-lang.org/style-guide.html#_getters_and_setters 如果您想了解有关此主题的更多信息,请搜索 groovy propertyMissing/groovy metaprogramming/groovy Resolve Strategies。
【讨论】:
我尝试使用像您这样的传递变量,然后将其分配给jvmArgs
。令人困惑的是,传递变量的打印输出与预期的一样,它的行为就像正常的集合,但jvmArgs
又是空的。我没有尝试过addAll()
,但我怀疑它会产生相同的效果。
感谢源代码,它看起来像是我正在寻找的解释。你是怎样找到它的?你是如何弄清楚事件链的?是否可以调试 Gradle?
@Espinosa 我已经更新了答案。可以肯定地调试 gradle 脚本,但我从来没有让它工作。我想我已经在 gradle docs 中找到了 javaExec 任务的起点,后来切换到了 github。以上是关于Gradle 不收集以 -D 开头的字符串的主要内容,如果未能解决你的问题,请参考以下文章
如何让 CSS 选择以字符串开头的 ID(不是在 Javascript 中)?