如何向Gradle JavaExec任务添加类路径以执行可运行的jar?

时间:2019-04-20 00:46:41

标签: java spring gradle

我的应用程序需要spring-context库。因此,在我的build.gradle文件中,添加了此依赖项,

dependencies {
    compile 'org.springframework:spring-context:5.1.6.RELEASE'
}

我还想创建一个可运行的jar文件,jar任务看起来像

jar {
    manifest {
        attributes 'Main-Class': 'my.package.my.main.class'
    }
}

启动构建文件后,一切都很好,

gradle build

但是当我尝试执行此可运行的jar应用程序时,

task runJar(dependsOn: jar, type: JavaExec) {
    classpath(configurations.compile)
    main = '-jar'; args 'build/libs/my-runnable.jar'
}

控制台抛出NoClassDefFoundError

Exception in thread "main" java.lang.NoClassDefFoundError: 
org/springframework/context/ConfigurableApplicationContext
...
...

我尝试过sourceSets.main.runtimeClasspath,问题仍然存在,

task runJar(dependsOn: jar, type: JavaExec) {
    classpath(sourceSets.main.runtimeClasspath)
    main = '-jar'; args 'build/libs/my-runnable.jar'
}

我检查了classpath个文件集合,

classpath.each {
    println it.name
}

spring-context包就在那里,

spring-context-5.1.6.RELEASE.jar
spring-aop-5.1.6.RELEASE.jar
spring-beans-5.1.6.RELEASE.jar
spring-expression-5.1.6.RELEASE.jar
spring-core-5.1.6.RELEASE.jar
spring-jcl-5.1.6.RELEASE.jar

然后,我尝试了另一种遍历方法来解决此问题。我从这些.jar库中提取了所有类文件,并将它们直接包含在我的最终runnable.jar中,

jar {
    manifest {
        attributes 'Main-Class': 'my.package.my.main.class'
    }

    configurations.compile.each {
        from(project.zipTree(it))
    }
}

此解决方案有效。但是这样的“胖子”不是我想要的。

我是gradle的新来者。这真的让我感到困惑。有人可以帮忙吗?谢谢!

1 个答案:

答案 0 :(得分:0)

工作大约3个小时后,一个简单的事实是:

  

当您指定-jar时,-cp参数将被忽略。

这个问题有一些详细的讨论:

  

Run a JAR file from the command line and specify classpath

有2种简单的解决方案:

  1. 正如我在问题中提到的,将所有.class文件直接提取到您的可执行jar中。
jar {
    manifest {
        attributes 'Main-Class': 'my.package.my.main.class'
    }

    configurations.compile.each {
        from(project.zipTree(it))
    }
}
  1. 第二种解决方法是在Class-Path文件中添加一个manifest参数。
jar {
    manifest {
        attributes 'Main-Class': 'your.main.class.full.name'
        attributes 'Class-Path': configurations.compile.collect { it.name }.join(' ')
    }
}

确保您可以在本地系统中找到.jar个库。例如,只需将它们复制到同一目录中,

task copyLibs(type: Copy) {
    from configurations.compile
    into 'build/libs/'
}

之后,我的build/libs/目录如下所示,

build
├── libs
│   ├── my-runnable-app.jar
│   ├── spring-aop-5.1.6.RELEASE.jar
│   ├── spring-beans-5.1.6.RELEASE.jar
│   ├── spring-context-5.1.6.RELEASE.jar
│   ├── spring-core-5.1.6.RELEASE.jar
│   ├── spring-expression-5.1.6.RELEASE.jar
│   └── spring-jcl-5.1.6.RELEASE.jar

请注意,所有.jar库都位于my-runnable-app.jar之外。如果您想将它们包括在my-runnable-app.jar中,则需要One-Jar工具箱。有关One-Jar的更多信息,请阅读以下问题:

  

Reference jars inside a jar