1. 概述

在使用 Gradle 构建项目时,我们经常需要执行一些外部程序或 Java 主类,而这些程序往往依赖命令行参数来控制行为。比如指定环境、传入配置项,甚至动态开启某些功能。

本文将带你掌握如何在 Gradle 中正确地向 Java 应用或其他外部命令传递命令行参数,避免踩坑。✅

2. 输入参数的类型

从 Gradle 命令行传参,主要有两种方式:

  • 使用 -D 设置 JVM 系统属性(System Properties)
  • 使用 -P 设置 项目属性(Project Properties)

⚠️ 关键区别:

类型 设置方式 读取方式 未定义时行为
Project Property -Pkey=value project.hasProperty("key") + project.getProperty("key") ❌ 抛出 MissingPropertyException
System Property -Dkey=value System.getProperty("key") ✅ 返回 null

📌 最佳实践建议:除非你要调整 JVM 参数(如 -Dfile.encoding=UTF-8),否则一律优先使用 -P 传参。

虽然也能用 -D 来传业务参数,但容易和 JVM 自身配置混淆,后期维护容易翻车。

来看一个例子,在 build.gradle 中定义任务:

apply plugin: "java"
description = "Gradle Command Line Arguments examples"

task propertyTypes() {
    doLast {
        if (project.hasProperty("args")) {
            println "Our input argument with project property [" + project.getProperty("args") + "]"
        }
        println "Our input argument with system property [" + System.getProperty("args") + "]"
    }
}

运行命令:

$ ./gradlew propertyTypes -Dargs=lorem -Pargs=ipsum

> Task :cmd-line-args:propertyTypes
Our input argument with project property [ipsum]
Our input argument with system property [lorem]

结果一目了然:-P 影响的是 Gradle 项目属性,-D 影响的是 JVM 层面的系统属性。

3. 向程序传递命令行参数

光读到参数还不够,关键是把它们传给目标程序。下面分场景说明。

3.1 向 Java 应用传递参数

方式一:使用 Application 插件(推荐,简单粗暴)

如果你的项目用了 application 插件,Gradle 提供了一个非常方便的 --args 参数。

先配置 build.gradle

apply plugin: "java"
apply plugin: "application"
description = "Gradle Command Line Arguments examples"

ext.javaMainClass = "com.baeldung.cmd.MainClass"

application {
    mainClassName = javaMainClass
}

Java 主类示例:

public class MainClass {
    public static void main(String[] args) {
        System.out.println("Gradle command line arguments example");
        for (String arg : args) {
            System.out.println("Got argument [" + arg + "]");
        }
    }
}

运行时直接加 --args

$ ./gradlew :cmd-line-args:run --args="lorem ipsum dolor"

> Task :cmd-line-args:run
Gradle command line arguments example
Got argument [lorem]
Got argument [ipsum]
Got argument [dolor]

✅ 优点:简洁明了,适合大多数场景。
⚠️ 注意:--args 支持从 Gradle 4.9 开始,老版本不支持。

方式二:自定义 JavaExec 任务(灵活可控)

如果需要更精细控制(比如不同环境传不同参数),可以手写 JavaExec 任务。

ext.javaMainClass = "com.baeldung.cmd.MainClass"
if (project.hasProperty("args")) {
    ext.cmdargs = project.getProperty("args")
} else { 
    ext.cmdargs = ""
}

task cmdLineJavaExec(type: JavaExec) {
    group = "Execution"
    description = "Run the main class with JavaExecTask"
    classpath = sourceSets.main.runtimeClasspath
    main = javaMainClass
    args cmdargs.split()
}

运行命令:

$ ./gradlew cmdLineJavaExec -Pargs="lorem ipsum dolor"

> Task :cmd-line-args:cmdLineJavaExec
Gradle command line arguments example
Got argument [lorem]
Got argument [ipsum]
Got argument [dolor]

💡 技巧:args cmdargs.split() 会按空格拆分字符串成数组,自动处理多个参数。

⚠️ 踩坑提醒:别忘了 split(),否则整个字符串会被当作一个参数传进去!

3.2 向外部程序传递参数

有时候你想调用 shell 命令、Python 脚本或其他可执行文件,这时候可以用 Gradle 的 Exec 任务。

if (project.hasProperty("args")) {
    ext.cmdargs = project.getProperty("args")
} else { 
    ext.cmdargs = "ls"
}

task cmdLineExec(type: Exec) {
    group = "Execution"
    description = "Run an external program with ExecTask"
    commandLine cmdargs.split()
}

比如运行 ls -ll

$ ./gradlew cmdLineExec -Pargs="ls -ll"

> Task :cmd-line-args:cmdLineExec
total 4
drwxr-xr-x 1 user 1049089    0 Sep  1 17:59 bin
drwxr-xr-x 1 user 1049089    0 Sep  1 18:30 build
-rw-r--r-- 1 user 1049089 1016 Sep  3 15:32 build.gradle
drwxr-xr-x 1 user 1049089    0 Sep  1 17:52 src

✅ 这种方式特别适合写 CI/CD 脚本,动态执行命令,避免硬编码。

💡 提示:commandLine 接收的是字符串数组,所以 split() 是关键,否则命令会被整体当作程序名。

4. 总结

场景 推荐方式 示例
执行 Java 主类(简单) application 插件 + --args ./gradlew run --args="dev port=8080"
执行 Java 主类(复杂) 自定义 JavaExec 任务 args project.getProperty('args').split()
执行外部命令 Exec 任务 commandLine 'python', 'script.py', 'arg1'
参数传递 优先使用 -P -Penv=prod -Pdebug=true

📌 核心要点:

  • ✅ 优先使用 -P 传项目属性,清晰且安全
  • --argsapplication 插件的语法糖,方便但有版本限制
  • JavaExecExec 提供最大灵活性,适合封装通用任务
  • ❌ 避免滥用 -D 来传业务参数,容易引发歧义

完整代码示例已上传至 GitHub:https://github.com/baeldung/tutorials/tree/master/gradle-modules/gradle-5/cmd-line-args


原始标题:Passing Command Line Arguments in Gradle