繁体   English   中英

如何使用 Gradle 和实现依赖项创建可执行的胖 JAR?

[英]How do I create an executable fat JAR with Gradle with implementation dependencies?

我在 Gradle 4.6 中有一个简单的项目,并且想制作一个可执行的 JAR 。 我已经尝试过shadowgradle-fatjar-plugingradle-one-jarspring-boot-gradle-plugin插件,但它们都没有添加我声明为implementation的依赖项(我没有任何compile依赖项)。 它适用于compile ,例如gradle-one-jar插件,但我希望有implementation依赖项。

我在Gradle 4.6中有一个简单的项目,并希望制作一个可执行的jar。 我试过了shadowgradle-fatjar-plugingradle-one-jarspring-boot-gradle-plugin插件,但是它们都没有添加我的依赖声明为implementation (我没有任何compile的依赖)。 它可以与gradle-one-jar插件进行compile ,但是我希望implementation依赖。

非常感谢你!

我在Gradle 4.6中有一个简单的项目,并希望制作一个可执行的jar。 我试过了shadowgradle-fatjar-plugingradle-one-jarspring-boot-gradle-plugin插件,但是它们都没有添加我的依赖声明为implementation (我没有任何compile的依赖)。 它可以与gradle-one-jar插件进行compile ,但是我希望implementation依赖。

非常感谢你!

我在Gradle 4.6中有一个简单的项目,并希望制作一个可执行的jar。 我试过了shadowgradle-fatjar-plugingradle-one-jarspring-boot-gradle-plugin插件,但是它们都没有添加我的依赖声明为implementation (我没有任何compile的依赖)。 它可以与gradle-one-jar插件进行compile ,但是我希望implementation依赖。

非常感谢你!

以前的答案现在有点过时了,请参阅此处了解使用 gradle-7.4 的内容: How to create a fat JAR with Gradle Kotlin script?

tasks.jar {
    manifest.attributes["Main-Class"] = "com.example.MyMainClass"
    val dependencies = configurations
        .runtimeClasspath
        .get()
        .map(::zipTree) // OR .map { zipTree(it) }
    from(dependencies)
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}

这里我提供Kotlin DSL (build.gradle.kts)的解决方案。
注意前3种方法修改了Gradle的现有Jar任务。

方法一:将库文件放在结果JAR旁边

此方法不需要application或任何其他插件。

tasks.jar {
    manifest.attributes["Main-Class"] = "com.example.MyMainClass"
    manifest.attributes["Class-Path"] = configurations
        .runtimeClasspath
        .get()
        .joinToString(separator = " ") { file ->
            "libs/${file.name}"
        }
}

请注意,Java 要求我们为Class-Path属性使用相对 URL。 所以,我们不能使用 Gradle 依赖的绝对路径(这也容易被改变,在其他系统上不可用)。 如果您想使用绝对路径,也许这种解决方法会起作用。

使用以下命令创建 JAR:

./gradlew jar

结果 JAR 默认会在build/libs/目录下创建。

创建 JAR 后,将库 JARs 复制到您放置结果 JAR 的libs/子目录中。 确保您的库 JAR 文件的文件名中不包含空格(它们的文件名应与上述任务中${file.name}变量指定的文件名匹配)。

方法 2:将库嵌入结果 JAR(胖或超级 JAR)

此方法也不需要任何 Gradle 插件。

tasks.jar {
    manifest.attributes["Main-Class"] = "com.example.MyMainClass"
    val dependencies = configurations
        .runtimeClasspath
        .get()
        .map(::zipTree) // OR .map { zipTree(it) }
    from(dependencies)
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}

创建 JAR 与前面的方法完全相同。

方法 3:使用Shadow 插件(创建 fat 或 uber JAR)

plugins {
    id("com.github.johnrengelman.shadow") version "6.0.0"
}
// Shadow task depends on Jar task, so these configs are reflected for Shadow as well
tasks.jar {
    manifest.attributes["Main-Class"] = "org.example.MainKt"
}

使用以下命令创建 JAR:

./gradlew shadowJar

有关配置插件的更多信息,请参阅Shadow 文档

方法四:新建任务(而不是修改Jar任务)

tasks.create("MyFatJar", Jar::class) {
    group = "my tasks" // OR, for example, "build"
    description = "Creates a self-contained fat JAR of the application that can be run."
    manifest.attributes["Main-Class"] = "com.example.MyMainClass"
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
    val dependencies = configurations
        .runtimeClasspath
        .get()
        .map(::zipTree)
    from(dependencies)
    with(tasks.jar.get())
}

运行创建的 JAR

java -jar my-artifact.jar

上述解决方案经过以下测试:

  • Java 17
  • Gradle 7.1(对.kts构建脚本使用 Kotlin 1.4.31)

有关创建 uber (fat) JARs 的信息,请参阅官方 Gradle 文档

有关清单的更多信息,请参阅Oracle Java 文档:使用清单文件

有关tasks.create()tasks.register()之间的区别,请参阅这篇文章

请注意,您的资源文件将自动包含在 JAR 文件中(假设它们被放置在/src/main/resources/目录或在构建文件中设置为资源根目录的任何自定义目录中)。 要访问应用程序中的资源文件,请使用以下代码(注意名称开头的/ ):

  • Kotlin
     val vegetables = MyClass::class.java.getResource("/vegetables.txt").readText() // Alternative ways: // val vegetables = object{}.javaClass.getResource("/vegetables.txt").readText() // val vegetables = MyClass::class.java.getResourceAsStream("/vegetables.txt").reader().readText() // val vegetables = object{}.javaClass.getResourceAsStream("/vegetables.txt").reader().readText()
  • Java
     var stream = MyClass.class.getResource("/vegetables.txt").openStream(); // OR var stream = MyClass.class.getResourceAsStream("/vegetables.txt"); var reader = new BufferedReader(new InputStreamReader(stream)); var vegetables = reader.lines().collect(Collectors.joining("\n"));

我在Gradle 4.6中有一个简单的项目,并希望制作一个可执行的jar。 我试过了shadowgradle-fatjar-plugingradle-one-jarspring-boot-gradle-plugin插件,但是它们都没有添加我的依赖声明为implementation (我没有任何compile的依赖)。 它可以与gradle-one-jar插件进行compile ,但是我希望implementation依赖。

非常感谢你!

我在Gradle 4.6中有一个简单的项目,并希望制作一个可执行的jar。 我试过了shadowgradle-fatjar-plugingradle-one-jarspring-boot-gradle-plugin插件,但是它们都没有添加我的依赖声明为implementation (我没有任何compile的依赖)。 它可以与gradle-one-jar插件进行compile ,但是我希望implementation依赖。

非常感谢你!

mainClassName = 'Main'
sourceSets {
    main {
        java {
            srcDirs 'src/main/java', 'src/main/resources'
        }
    }
}
jar{
    manifest {
        attributes(
                "Main-Class": "$mainClassName",

        )

    }
    from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) 
         }
    }
    exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
    dependsOn ('dependencies')
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM