Gradle执行Java类(无需修改build.gradle)

134

有一个简单的Eclipse插件可以运行Gradle,它只是使用命令行方式启动Gradle。

对于maven的compile和run,gradle的类比是什么? mvn compile exec:java -Dexec.mainClass=example.Example

这样任何包含gradle.build的项目都可以运行。

更新:之前有类似的问题“运行Java应用程序的Maven插件exec在Gradle中有什么等价物?”,但建议的解决方案是修改每个项目的build.gradle文件。

package runclass;

public class RunClass {
    public static void main(String[] args) {
        System.out.println("app is running!");
    }
}

然后执行 gradle run -DmainClass=runclass.RunClass

:run FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':run'.
> No main class specified   

可能是 https://dev59.com/D2Qo5IYBdhLWcg3wE74J?rq=1 的重复问题。 - Teresa Carrigan
使用命令:gradle run - Alexei
4个回答

161

在Gradle中没有mvn exec:java的直接等价物,您需要应用application插件或者添加一个JavaExec任务。

application插件

激活插件:

plugins {
    id 'application'
    ...
}

按照以下方式配置:

application {
    mainClassName = project.hasProperty("mainClass") ? project.getProperty("mainClass") : "NULL"
}

在命令行中,输入

$ gradle -PmainClass=Boo run

JavaExec任务

定义一个任务,比如说execute

task execute(type:JavaExec) {
   main = project.hasProperty("mainClass") ? getProperty("mainClass") : "NULL"
   classpath = sourceSets.main.runtimeClasspath
}

要运行,请输入gradle -PmainClass=Boo execute。你将得到

$ gradle -PmainClass=Boo execute
:compileJava
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes
:execute
I am BOO!

mainClass 是在命令行动态传递的属性。classpath 被设置为获取最新的类。


如果您没有传递 mainClass 属性,则这两种方法都会按预期失败。

$ gradle execute

FAILURE: Build failed with an exception.

* Where:
Build file 'xxxx/build.gradle' line: 4

* What went wrong:
A problem occurred evaluating root project 'Foo'.
> Could not find property 'mainClass' on task ':execute'.

3
你需要修改 build.gradle,其中 classpath 是硬编码的,以从 build.gradle [tag:java] 源类路径中获取类。即使你运行了 mvn exec:java,类路径也被设置为从当前maven目录中获取java源文件。在 JavaExec 任务中,我已经做了同样的事情。更改 [tag:java] 源代码的 classpath,类路径将自动更改。在 gradle 中没有 - mvn exec:java 的等效项,你需要应用 application 插件或拥有一个 JavaExec 任务。 - First Zero
1
或者另一种选择是编写自己的插件来完成此操作,即使如此,您也必须更改build.gradle以使用您的插件。 - First Zero
3
我刚试了一下,在build.gradle中加入task execute(...后,其他任务都会失败,并显示相同的错误消息,说明Gradle希望传递mainClass。我无法执行clean或build。 - Nirro
6
main = mainClass 替换为 main = getProperty("mainClass") ,它就不会再向你大喊大叫了。 - Adi Gerber
2
这仍然会导致“gradle build”失败,请参见我下面的答案。 - Matt
显示剩余7条评论

146
你只需要使用Gradle 应用插件
apply plugin:'application'
mainClass = "org.gradle.sample.Main"

然后只需运行gradle run

正如Teresa所指出的那样,您也可以将mainClass配置为系统属性,并使用命令行参数运行。


3
这需要将每个这样的类硬编码到 build.gradle 文件中。但是我有一个包含许多实用程序类的项目,每个类都有主方法。 - Paul Verest
你确定以下几点:1)完全限定类名是正确的;2)在构建文件中使用了正确的属性名称,例如System.getProperty("mainClass");3)源代码按照约定放置在正确的位置;4)当你在构建文件中加入RunClass时一切都能正常工作? - Vidya
只有当 build.gradle 中设置了 mainClassName = "runclass.RunClass" 才能正常工作。参数 -DmainClass 没有任何效果:gradle run -DmainClass=runclass.RunClass2 会执行硬编码的主类。 - Paul Verest
3
如果你同时使用文件构建方法和属性方法,我其实不知道哪个方法会优先生效。你应该找到答案,或者在测试中不要同时使用两种方法。 - Vidya
2
@PaulVerest 这是我所做的:ext.mainClass = project.hasProperty('mainClass') ? project.getProperty('mainClass') : 'org.gradle.sample.Main' ; apply plugin:'application' ; mainClassName = ext.mainClass现在,当您执行 gradle -PmainClass=Foo run 时,它应该将 Foo 作为主类。 - msridhar
传递参数:https://dev59.com/rV4c5IYBdhLWcg3wucQt - Leon

30

在First Zero的回答基础上进行拓展,我猜你想要一个可以运行gradle build且不会出错的方法。

使用以下两种方式均可实现gradle buildgradle -PmainClass=foo runApp

task runApp(type:JavaExec) {
    classpath = sourceSets.main.runtimeClasspath

    main = project.hasProperty("mainClass") ? project.getProperty("mainClass") : "package.MyDefaultMain"
}

你可以在这里设置默认的主类。


3
我认为这应该是被采纳的答案。使用FirstZero或Vidya的方法会导致其他任务出现问题,因为主类没有被指定。 - yanhan
Matt的设置主值的方法同样适用于应用程序插件。我正在使用Gradle Kotlin DSL:plugins { application }; application { mainClassName = if (project.hasProperty("mainClass")) project.properties.get("mainClass").toString() else "Foo" } - pvillela
@Matt,这种方法破坏了我使用Scanner读取nextLine()的简单Java程序。你有没有想过修复它的方法?在使用runApp运行时仍然会收到“未找到行”的错误提示。 - Greg Hilston
2
如果有人在未来阅读这篇文章,我使用了 standardInput = System.in 来允许我的 Gradle 执行仍然可以传入输入。 - Greg Hilston

1

您可以对其进行参数化,并传递 gradle clean build -Pprokey=goodbye。

task choiceMyMainClass(type: JavaExec) {
     group = "Execution"
    description = "Run Option main class with JavaExecTask"
    classpath = sourceSets.main.runtimeClasspath

    if (project.hasProperty('prokey')){
        if (prokey == 'hello'){
            main = 'com.sam.home.HelloWorld'
        } 
        else if (prokey == 'goodbye'){
            main = 'com.sam.home.GoodBye'
        }
    } else {
            println 'Invalid value is enterrd';

       // println 'Invalid value is enterrd'+ project.prokey;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接