【问题标题】:How to add classpath to Gradle JavaExec task to execute a runnable jar?如何将类路径添加到 Gradle JavaExec 任务以执行可运行的 jar?
【发布时间】:2019-09-10 03:56:22
【问题描述】:

我的应用程序需要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的新手。这真的让我很困惑。任何人都可以帮忙吗?谢谢!

【问题讨论】:

    标签: java spring gradle


    【解决方案1】:

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

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

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

    Run a JAR file from the command line and specify classpath

    有两种简单的解决方案:

    1. 正如我在问题中提到的,将所有 .class 文件直接提取到可执行 jar 中。
    jar {
        manifest {
            attributes 'Main-Class': 'my.package.my.main.class'
        }
    
        configurations.compile.each {
            from(project.zipTree(it))
        }
    }
    
    1. 第二种解决方案是在manifest文件中添加Class-Path参数。
    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

    【讨论】:

      猜你喜欢
      • 2021-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-13
      • 1970-01-01
      • 2018-09-26
      • 1970-01-01
      相关资源
      最近更新 更多