簡體   English   中英

"使用 Gradle 創建可運行的 JAR"

[英]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,以及一個啟動腳本,該腳本將所有這些組合到一個您可以運行的程序中
  • distZipdistTar任務創建包含完整應用程序分發(啟動腳本和 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 > 來自具有依賴項的模塊。
  • 設置主類。

制作 jar 就像從 Build 菜單中單擊“Build artifact...”一樣簡單。 作為獎勵,您可以將所有依賴項打包到一個 jar 中。

在 IntelliJ IDEA 14 Ultimate 上測試。

我檢查了很多解決方案的鏈接,最后執行了下面提到的步驟以使其正常工作。 我正在使用 Gradle 2.9。

在您的 build,gradle 文件中進行以下更改:

  1. 提及插件:

     apply plugin: 'eu.appsatori.fatjar'
  2. 提供構建腳本:

     buildscript { repositories { jcenter() } dependencies { classpath "eu.appsatori:gradle-fatjar-plugin:0.3" } }
  3. 提供主類:

     fatJar { classifier 'fat' manifest { attributes 'Main-Class': 'my.project.core.MyMainClass' } exclude 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.SF' }
  4. 創建胖子:

     ./gradlew clean fatjar
  5. 從 /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
    }

如何使用 ?

  • 將上述任務添加到 build.gradle
  • 執行gradle fatJar //創建 fatJar
  • 執行gradle createJar // 創建 jar 並復制依賴項。

更多細節: https : //jafarmlp.medium.com/a-simple-java-project-with-gradle-2c323ae0e43d

  1. 將主類配置到您的清單

如果您使用的是 gradle 項目,只需將以下內容添加到您的 build.gradle 中

jar {
    manifest {
        attributes(
               'Main-Class': 'pokerhandscorer.PokerHandScorer'
        )
    }
}
  • 其中'pokerhandscorer'是包名,PokerHandScorer是主類名

這會在您的 \\build\\libs{jarFilename}.jar 中創建一個 jar 文件

  1. 使用 java -jar /{path}/{jarFileName.jar} 運行 jar 文件

java -jar /{path}/{jarFileName.jar}

這適用於 Kotlin DSL (build.gradle.kts)。

方法1(不需要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 文檔

運行創建的 JAR

java -jar my-artifact.jar

上述解決方案經過以下測試:

  • 爪哇 17
  • Gradle 7.1(將 Kotlin 1.4.31 用於.kts腳本)

有關更多信息,請參閱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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM