以下是四种实现方法。请注意,前三种方法会修改Gradle的现有Jar任务。
方法1:将库文件放在与结果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要求我们使用相对URL来设置
Class-Path
属性。因此,我们不能使用Gradle依赖项的绝对路径(这也容易被更改并且不可用于其他系统)。如果您想使用绝对路径,也许
this workaround可以起作用。
使用以下命令创建JAR:
./gradlew jar
默认情况下,结果JAR将在build/libs/目录中创建。
创建JAR文件后,请将库JAR复制到结果JAR所在目录的libs/子目录中。确保您的库JAR文件名称中不包含空格(它们的文件名应与任务中上面指定的${file.name}
变量匹配)。
方法2:将库嵌入结果JAR文件中(fat或uber JAR)
这种方法也不需要任何Gradle插件。
tasks.jar {
manifest.attributes["Main-Class"] = "com.example.MyMainClass"
val dependencies = configurations
.runtimeClasspath
.get()
.map(::zipTree)
from(dependencies)
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
创建JAR文件的方法与之前的方法完全相同。
方法三:使用Shadow插件(创建fat或uber JAR文件)
plugins {
id("com.github.johnrengelman.shadow") version "6.0.0"
}
tasks.jar {
manifest.attributes["Main-Class"] = "com.example.MyMainClass"
}
使用以下命令创建JAR文件:
./gradlew shadowJar
请参阅Shadow文档以获取有关配置插件的更多信息。
方法4:创建新任务(而不是修改Jar
任务)
tasks.create("MyFatJar", Jar::class) {
group = "my tasks"
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(使用 Kotlin 1.4.31 进行 .kts 构建脚本)
请参阅官方 Gradle 文档以创建 uber (fat) JARs。
有关清单的更多信息,请参见 Oracle Java 文档:使用清单文件。
有关 tasks.create()
和 tasks.register()
之间的区别,请参见 此帖子。
请注意,您的 资源文件将自动包含在 JAR 文件中(假设它们放置在 /src/main/resources/ 目录或在构建文件中设置为资源根目录的任何自定义目录中)。要访问应用程序中的资源文件,请使用此代码(请注意名称开头的 /
):
- Kotlin
val vegetables = MyClass::class.java.getResource("/vegetables.txt").readText()
- Java
var stream = MyClass.class.getResource("/vegetables.txt").openStream();
var reader = new BufferedReader(new InputStreamReader(stream));
var vegetables = reader.lines().collect(Collectors.joining("\n"));