通过 Gradle 运行 Java 类时传递系统属性和参数的问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23689054/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Problems passing system properties and parameters when running Java class via Gradle
提问by sparc_spread
I am trying to run a command-line Java app via Gradle as part of a quick integration test. I am porting my build scripts from Maven, where this was easily done via exec-maven-plugin
. My two big requirements are:
作为快速集成测试的一部分,我正在尝试通过 Gradle 运行命令行 Java 应用程序。我正在从 Maven 移植我的构建脚本,这很容易通过exec-maven-plugin
. 我的两大要求是:
- Being able to pass system properties to the executable Java code
- Being able to pass command-line args to the executable Java code
- 能够将系统属性传递给可执行的 Java 代码
- 能够将命令行参数传递给可执行的 Java 代码
Please note that I am not trying to read these properties in the build script, I'm trying to read them in the Java program that the script builds and executes.
请注意,我不是试图在构建脚本中读取这些属性,而是尝试在脚本构建和执行的 Java 程序中读取它们。
I have found two other SO posts that address Java program execution via Gradle: one with an answer that advocates using apply plugin: "application"
in the build file and gradle run
at the command line, and 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. I have tried both approaches and have not succeeded.
我发现另外两个SO职位,透过摇篮地址的Java程序执行:一个与使用倡导者答案apply plugin: "application"
在构建文件,并gradle run
在命令行中,和其他的答案提倡的做法以及使用task execute(type:JavaExec)
的构建文件,并gradle execute
在命令行。这两种方法我都试过了,都没有成功。
I have two problems:
我有两个问题:
(1) I cannot get the Java executable to read the system properties
(1) 我无法让 Java 可执行文件读取系统属性
Whether I do this:
我是否这样做:
build.gradle:
构建.gradle:
apply plugin: 'application'
mainClassName = "com.mycompany.MyMain"
Command line:
命令行:
gradle run -Dmyproperty=myvalue
Or this:
或这个:
build.gradle:
构建.gradle:
task execute (type:JavaExec) {
main = "com.mycompany.MyMain"
classpath = sourceSets.main.runtimeClasspath
}
Command line:
命令行:
gradle execute -Dmyproperty=myvalue
In either case, myproperty
does not make it through. The code that begins running from MyMain.main (...)
reads the myproperty
system property as null/missing.
无论哪种情况,myproperty
都无法通过。开始运行的代码MyMain.main (...)
将myproperty
系统属性读取为空/缺失。
(2) I cannot pass command line arguments
(2) 我不能传递命令行参数
This is probably related to the first problem. In exec-maven-plugin
, for example, command line args were themselves passed in via a system property. Is that the case with Gradle, or is there another way to pass command line arguments?
这可能与第一个问题有关。exec-maven-plugin
例如,在 中,命令行参数本身是通过系统属性传入的。Gradle 是这种情况,还是有另一种传递命令行参数的方法?
How do I get these variables through? Also, is it better to use apply plugin: 'application'
or task execute (type:JavaExec)
?
我如何获得这些变量?另外,使用apply plugin: 'application'
还是更好task execute (type:JavaExec)
?
采纳答案by sparc_spread
Figured it out. The main issue is that when Gradle forks a new Java process, it does not automatically pass the environment variable values along to the new environment. One has to explicitly pass these variables via the systemProperties
property of the task or plugin.
弄清楚了。主要问题是当 Gradle 派生一个新的 Java 进程时,它不会自动将环境变量值传递给新环境。必须通过systemProperties
任务或插件的属性显式传递这些变量。
The other issue was understanding how to pass command-line args; these are via the args
property on the task or plugin. As with the Maven exec-maven-plugin
, they should be passed in on the command line via yet another system property, as a space-delimited list that then needs to be split()
before setting args
, which accepts List
objects. I've named the property exec.args
, which is the old Maven name.
另一个问题是了解如何传递命令行参数;这些是通过args
任务或插件上的属性。与 Maven 一样exec-maven-plugin
,它们应该通过另一个系统属性在命令行上传递,作为一个空格分隔的列表,然后需要split()
在设置之前args
,它接受List
对象。我已经命名了 property exec.args
,这是旧的 Maven 名称。
It seems both the javaExec
and application plugin approach are valid. One might favor the application plugin approach if one wants to use some of its other features (automatically putting together a distribution, etc.)
似乎javaExec
应用程序插件方法和应用程序插件方法都是有效的。如果想要使用应用程序插件的一些其他功能(自动组合发行版等)
Here are the solutions:
以下是解决方案:
JavaExec Approach
JavaExec 方法
Command Line:
命令行:
gradle execute -Dmyvariable=myvalue -Dexec.args="arg1 arg2 arg3"
build.gradle:
构建.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()
}
Application Plugin Approach
应用插件方法
Command Line:
命令行:
gradle run -Dmyvariable=myvalue -Dexec.args="arg1 arg2 arg3"
build.gradle:
构建.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()
}
回答by geg
For those who might not want to pollute your application's system properties by passing unrelated Gradle props, I recommend namespacing your arguments.
对于那些可能不想通过传递不相关的 Gradle 道具来污染应用程序系统属性的人,我建议您对参数进行命名空间。
tasks.withType(JavaExec) {
System.properties.each { k,v->
if (k.startsWith("prefix.")) {
systemProperty k - "prefix.", v
}
}
}
java ... -Dprefix.my.prop=true
will pass my.prop
java ... -Dprefix.my.prop=true
将通过 my.prop
回答by Stan Towianski
I'm new to gradle so I needed this and what is working for me with gradle 4.6 seems a little easier for the command line. Instead of parsing 1 arg string you can pass an array of args, and I found a way to pass in all property with one line as well. Combined below:
我是 gradle 的新手,所以我需要这个,而 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=
回答by WesternGun
Maybe I am late for the party, but has anyone tried with "set the prop before executing gradle"? I have tested and this works too, apparently.
也许我参加聚会迟到了,但是有没有人尝试过“在执行 gradle 之前设置道具”?我已经测试过了,这显然也有效。
myVar=myVal gradle test
For example, you can set the active profile like:
例如,您可以将活动配置文件设置为:
SPRING_PROFILES_ACTIVE=dev gradle test
These also work, apparently:(tested)
这些显然也有效:(已测试)
set myVar=myVal && gradle test # for windows
export myVar=myVal && gradle test # for linux and mac
Be wary that myVar
cannot be period-separated; or else only the part before the first period will be taken as key.
小心myVar
不能以句号分隔;否则只有第一期之前的部分将被视为关键。