[英]Creating runnable JAR with Gradle
到目前為止,我通過 Eclipse“導出...”功能創建了可運行的 JAR 文件,但現在我切換到 IntelliJ IDEA 和 Gradle 以實現構建自動化。
這里的一些文章建議使用“應用程序”插件,但這並不完全導致我預期的結果(只是一個 JAR,沒有啟動腳本或類似的東西)。
如何使用“導出...”對話框獲得與 Eclipse 相同的結果?
一個可執行的 jar 文件只是一個在其清單中包含一個 Main-Class 條目的 jar 文件。 因此,您只需要配置jar 任務即可在其清單中添加此條目:
jar {
manifest {
attributes 'Main-Class': 'com.foo.bar.MainClass'
}
}
您可能還需要在清單中添加類路徑條目,但這將以相同的方式完成。
請參閱http://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html
JB Nizet 和 Jorge_B 的答案都是正確的。
在最簡單的形式中,使用 Gradle 創建可執行 JAR 只是將適當的條目添加到manifest 的問題。 但是,需要將依賴項包含在類路徑中的情況更為常見,這使得這種方法在實踐中變得棘手。
應用程序插件提供了另一種方法; 它沒有創建可執行的 JAR,而是提供:
run
任務,以方便直接從構建中輕松運行應用程序installDist
任務,它生成一個目錄結構,包括構建的 JAR、它依賴的所有 JAR,以及一個啟動腳本,該腳本將所有這些組合到一個您可以運行的程序中distZip
和distTar
任務創建包含完整應用程序分發(啟動腳本和 JAR)的檔案第三種方法是創建一個所謂的“胖 JAR”,它是一個可執行的 JAR,不僅包含組件的代碼,還包含其所有依賴項。 有幾個不同的插件使用這種方法。 我已經包含了一些我知道的鏈接; 我確定還有更多。
正如其他人所指出的,為了使 jar 文件可執行,必須在清單文件的Main-Class
屬性中設置應用程序的入口點。 如果依賴類文件沒有並置,則需要在清單文件的Class-Path
條目中設置它們。
我已經嘗試了各種插件組合,而不是為了創建可執行 jar 的簡單任務,並以某種方式包含依賴項。 所有插件似乎都缺乏一種或另一種方式,但最終我得到了我想要的。 沒有神秘的腳本,沒有一百萬個不同的小文件污染構建目錄,一個非常干凈的構建腳本文件,最重要的是:沒有一百萬個外國第三方類文件合並到我的 jar 檔案中。
為了您的方便,以下是從這里復制粘貼..
[How-to] 在子目錄/lib
創建一個帶有依賴項 jar 的分發 zip 文件,並將所有依賴項添加到清單文件中的Class-Path
條目:
apply plugin: 'java'
apply plugin: 'java-library-distribution'
repositories {
mavenCentral()
}
dependencies {
compile 'org.apache.commons:commons-lang3:3.3.2'
}
// Task "distZip" added by plugin "java-library-distribution":
distZip.shouldRunAfter(build)
jar {
// Keep jar clean:
exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.MF'
manifest {
attributes 'Main-Class': 'com.somepackage.MainClass',
'Class-Path': configurations.runtime.files.collect { "lib/$it.name" }.join(' ')
}
// How-to add class path:
// https://stackoverflow.com/questions/22659463/add-classpath-in-manifest-using-gradle
// https://gist.github.com/simon04/6865179
}
在這里作為要點托管。
結果可以在build/distributions
找到,解壓后的內容如下所示:
lib/commons-lang3-3.3.2.jar
MyJarFile.jar
MyJarFile.jar#META-INF/MANIFEST.mf
:
清單版本:1.0
主類:com.somepackage.MainClass
類路徑:lib/commons-lang3-3.3.2.jar
對我來說最省力的解決方案是使用gradle-shadow-plugin
除了應用插件,所有需要做的是:
配置 jar 任務以將您的 Main 類放入清單
jar {
manifest {
attributes 'Main-Class': 'com.my.app.Main'
}
}
運行gradle任務
./gradlew shadowJar
從build/libs/獲取app-version-all.jar
最后通過以下方式執行它:
java -jar app-version-all.jar
您是否嘗試過“installApp”任務? 它不會創建一個包含一組啟動腳本的完整目錄嗎?
http://www.gradle.org/docs/current/userguide/application_plugin.html
您可以使用 SpringBoot 插件:
plugins {
id "org.springframework.boot" version "2.2.2.RELEASE"
}
創建罐子
gradle assemble
然后運行它
java -jar build/libs/*.jar
注意:您的項目不需要是 SpringBoot 項目即可使用此插件。
謝謝康斯坦丁,它就像一種魅力,幾乎沒有細微差別。 出於某種原因,將主類指定為 jar 清單的一部分並不完全有效,而是需要 mainClassName 屬性。 這是 build.gradle 中的一個片段,其中包含使其工作的所有內容:
plugins {
id 'java'
id 'com.github.johnrengelman.shadow' version '1.2.2'
}
...
...
apply plugin: 'application'
apply plugin: 'com.github.johnrengelman.shadow'
...
...
mainClassName = 'com.acme.myapp.MyClassMain'
...
...
...
shadowJar {
baseName = 'myapp'
}
運行 gradle shadowJar 后,您將在構建文件夾中獲得 myapp-{version}-all.jar,該文件夾可以作為 java -jar myapp-{version}-all.jar 運行。
您可以在模塊設置(或項目結構)中定義一個 jar 工件。
制作 jar 就像從 Build 菜單中單擊“Build artifact...”一樣簡單。 作為獎勵,您可以將所有依賴項打包到一個 jar 中。
在 IntelliJ IDEA 14 Ultimate 上測試。
我檢查了很多解決方案的鏈接,最后執行了下面提到的步驟以使其正常工作。 我正在使用 Gradle 2.9。
在您的 build,gradle 文件中進行以下更改:
提及插件:
apply plugin: 'eu.appsatori.fatjar'
提供構建腳本:
buildscript { repositories { jcenter() } dependencies { classpath "eu.appsatori:gradle-fatjar-plugin:0.3" } }
提供主類:
fatJar { classifier 'fat' manifest { attributes 'Main-Class': 'my.project.core.MyMainClass' } exclude 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.SF' }
創建胖子:
./gradlew clean fatjar
從 /build/libs/ 運行 fatjar:
java -jar MyFatJar.jar
這是我在 Gradle 6.7 上嘗試的解決方案
Runnable fat Jar(將所有依賴庫復制到 jar 中)
task fatJar(type: Jar) {
manifest {
attributes 'Main-Class': 'com.example.gradle.App'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
} with jar
}
將所有依賴項復制到目錄並將類路徑添加到清單的可運行 jar
def dependsDir = "${buildDir}/libs/dependencies/"
task copyDependencies(type: Copy) {
from configurations.compile
into "${dependsDir}"
}
task createJar(dependsOn: copyDependencies, type: Jar) {
manifest {
attributes('Main-Class': 'com.example.gradle.App',
'Class-Path': configurations.compile.collect { 'dependencies/' + it.getName() }.join(' ')
)
}
with jar
}
如何使用 ?
gradle fatJar
//創建 fatJargradle createJar
// 創建 jar 並復制依賴項。更多細節: https : //jafarmlp.medium.com/a-simple-java-project-with-gradle-2c323ae0e43d
如果您使用的是 gradle 項目,只需將以下內容添加到您的 build.gradle 中
jar {
manifest {
attributes(
'Main-Class': 'pokerhandscorer.PokerHandScorer'
)
}
}
這會在您的 \\build\\libs{jarFilename}.jar 中創建一個 jar 文件
java -jar /{path}/{jarFileName.jar}
這適用於 Kotlin DSL (build.gradle.kts)。
application
或其他插件)tasks.jar {
manifest.attributes["Main-Class"] = "com.example.MyMainClass"
// OR another notation
// manifest {
// attributes["Main-Class"] = "com.example.MyMainClass"
// }
}
如果您使用任何外部庫,請使用以下代碼。 將庫 JAR 放在放置結果 jar 的libs子目錄中。 確保您的庫 JAR 文件的文件名中不包含空格。
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/目錄中。
plugins {
id("com.github.johnrengelman.shadow") version "6.0.0"
}
// Shadow task depends on Jar task, so these will be reflected for Shadow as well
tasks.jar {
manifest.attributes["Main-Class"] = "org.example.MainKt"
}
使用以下命令創建 JAR:
./gradlew shadowJar
有關配置插件的更多信息,請參閱Shadow 文檔。
java -jar my-artifact.jar
上述解決方案經過以下測試:
有關更多信息,請參閱Oracle Java 文檔:使用清單文件。
請注意,您的資源文件將自動包含在 JAR 文件中(假設它們被放置在/src/main/resources/目錄或在構建文件中設置為資源根目錄的任何自定義目錄中)。 要訪問應用程序中的資源文件,請使用以下代碼:
val vegetables = MyClass::class.java.getResource("/vegetables.txt").readText() // OR // val vegetables = object{}.javaClass.getResource("/vegetables.txt").readText()
var stream = MyClass.class.getResourceAsStream("vegetables.txt");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.