我正在尝试通过Gradle运行命令行Java应用程序,作为快速集成测试的一部分。我正在从Maven移植我的构建脚本,这可以通过exec-maven-plugin
轻松完成。我的两大要求是:
请注意,我没有尝试在构建脚本中读取这些属性,我正在尝试在脚本构建和执行的Java程序中读取它们。
我找到了另外两篇SO帖子,通过Gradle解决了Java程序的执行问题:one with an answer that advocates using apply plugin: "application"
in the build file and gradle run
at the command line和another 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)我无法获取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
中,命令行参数本身是通过系统属性传入的。这是Gradle的情况,还是有另一种传递命令行参数的方法?
如何通过这些变量?另外,使用apply plugin: 'application'
或task execute (type:JavaExec)
?
答案 0 :(得分:112)
想出来。主要问题是,当Gradle分支新的Java进程时,它不会自动将环境变量值传递给新环境。必须通过任务或插件的systemProperties
属性显式传递这些变量。
另一个问题是了解如何传递命令行参数;这些是通过任务或插件上的args
属性。与Maven exec-maven-plugin
一样,它们应该通过另一个系统属性在命令行上传递,作为空格分隔的列表,然后在设置split()
之前需要args
,接受List
个对象。我已将该属性命名为exec.args
,这是旧的Maven名称。
似乎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()
}
答案 1 :(得分:11)
对于那些可能不想通过传递不相关的Gradle道具来污染应用程序的系统属性的人,我建议命名为你的参数。
tasks.withType(JavaExec) {
System.properties.each { k,v->
if (k.startsWith("prefix.")) {
systemProperty k - "prefix.", v
}
}
}
java ... -Dprefix.my.prop=true
将通过my.prop
答案 2 :(得分:1)
我是新手,所以我需要这个,并且使用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=
答案 3 :(得分:-1)
也许我参加聚会迟到了,但是有人尝试过“在执行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
不能用句点分隔;否则,仅将第一个期间之前的部分作为关键。