GradleとKotlinを使用して自己実行可能なjarを構築する
1. 序章
JVM言語は、ユーザーに「一度書けば、どこでも実行できる」と約束します。 ただし、出荷に関しては、多くの小さな問題が発生します。 エコシステムは進化しており、今では数十から数十の依存関係ライブラリなしでアプリケーションを作成することは考えられません。 それらはすべてクラスパスに含まれている必要があり、そうでない場合は、アプリケーションが起動しません。
別のディレクトリを作成し、そこにすべての依存関係jarを配置する余裕がある場合があります。 ただし、javaコマンドで実行できるuber-jarまたはfat-jarが必要な場合があります。
java -jar my-application.jar
Gradle でそれを実現する方法の1つは、私たちのサイトですでに説明されています。 他の可能性について話し合いましょう。 また、Groovyの代わりにKotlinGradleDSLをビルドファイルで使用します。
2. Gradleプラグインを使用した軽量アプリケーション
さて、「自己実行型jar」は少し誤称かもしれません。 アプリケーションをWindows、Linux、およびmacOSプラットフォームでCLIを使用せずに実行できるようにする場合は、標準のGradleプラグイン–アプリケーションを使用できます。
plugins {
application // enabling the plugin here
kotlin("jvm") version "1.6.0"
}
// Other configuration here
application {
mainClass.set("the.path.to.the.MainClass")
}
私たちがする必要があるのはアプリケーションのメインクラスを指す –関数を含むクラス main(args:配列
アプリケーションプラグインには、配布プラグインも自動的に含まれます。 配布プラグインは、TARとZIPの2つのアーカイブを作成します。 それらの内容は同一であり、プロジェクトjar、すべての依存関係jar、および2つのスクリプト(Bashと .bat ファイル)が含まれています。 次に、アプリケーションの配布はまったく問題ありません。 our-project / build / distributions / our-project-1.0.1.zip を使用して解凍し、実行可能スクリプトを実行できます。
unzip our-project-1.0.1.zip
./our-project-1.0.1/bin/our-project-1.0.1
これにより、LinuxとmacOSでアプリケーションが起動します。 コマンド./our-project-1.0.1 / bin / our-project-1.0.1.bat は、Windowsで起動します。
ただし、ソフトウェアをパックして配布するこの方法は理想的ではありません。 実際、ターゲットホスト上にTARまたはZIPアンアーカイバが存在し、有効なJREが存在することを前提としています。 転送するファイルの数を最小限に抑え、アプリケーションを起動する最も簡単な方法が必要な場合はどうなりますか?
ファットジャーに入ります。
3. 軽量アプリケーション用の「ファットジャー」
アプリケーションを出荷する次の方法は、前の章で説明したアプリケーションプラグインをビルドすることです。 目標を達成するためにカスタムタスクを追加します。
プロジェクトを3番目のプロジェクトの依存関係として使用する予定がない場合は、すべての依存関係を1つのjar にパックして、次のものを出荷します。
tasks {
val fatJar = register<Jar>("fatJar") {
dependsOn.addAll(listOf("compileJava", "compileKotlin", "processResources")) // We need this for Gradle optimization to work
archiveClassifier.set("standalone") // Naming the jar
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
manifest { attributes(mapOf("Main-Class" to application.mainClass)) } // Provided we set it up in the application plugin configuration
val sourcesMain = sourceSets.main.get()
val contents = configurations.runtimeClasspath.get()
.map { if (it.isDirectory) it else zipTree(it) } +
sourcesMain.output
from(contents)
}
build {
dependsOn(fatJar) // Trigger fat jar creation during build
}
}
JohnEngelmanのShadowJarプラグインの使用は、依存関係をシェーディングする必要がある場合にのみ必要になります。 依存関係をシェーディングするには、同じ依存関係の別のバージョンの重複するクラスファイルと衝突しないように、パッケージ名を書き直します。 ただし、実行可能jarが依存関係の候補になる可能性は低く、すべてのプロジェクトでそれをスキップできる可能性があります。
上記のコードは、プロジェクトの build /libsディレクトリにもう1つのjarファイルour-project-1.0.1-standalone.jarを生成します。 直接実行できます。
java -jar our-project-1.0.1-standalone.jar
3. SpringBootアプリケーション
SpringBootアプリケーションはすぐに実行可能です。 2番目のアプローチのようにすべてのjarを再パッケージ化する代わりに、SpringBootプラグインは依存関係jarをもう1つのjarでラップします。 この場合、プロジェクトの作成は簡単です。 Spring Initializr を使用して、プロジェクトで必要なテクノロジーを選択し、すぐに使用できるプロジェクトをダウンロードできます。 プラグインは私たちが望むすべてです:
plugins {
id("org.springframework.boot") version "2.6.0"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.6.0"
kotlin("plugin.spring") version "1.6.0"
}
次に、アプリケーションは有効なSpring Bootアプリケーションである必要があります。これは、クラスパスを操作するために、SpringBootがスターターを使用するためです。 Gradleビルドが成功すると、our-project-1.0.1.jarがbuild/libsディレクトリに見つかります。
java -jar our-project-1.0.1.jar
4. 結論
プロジェクト、そのサイズ、および使用するテクノロジーに応じて、解凍されたディストリビューション、自作のファットjar、影付きの依存関係を持つjar、またはSpringBootアプリケーションを選択する場合があります。 すべての場合において、Gradleは私たちの目標を達成するための簡単なツールを提供します。
自作のファットジャーとSpringBootアプリケーションのサンプルプロジェクトは、GitHubのにあります。