フレームワーク:Spring Boot
ビルドツール:Maven
という構成で、mvn installでjarを作成したとする。
このjarはどういう構成になっているのか?
jarは内部的にはzipなので、拡張子をzipに変更して解凍して確認してみた。
jar(zip)のルートディレクトリ
├─BOOT-INF
│ ├─classes
│ │ ├─com
│ │ │ └─example
│ │ │ └─[artifactId]
│ │ │ ├─controller
│ │ │ ├─dto
│ │ │ ├─mapper
│ │ │ ├─model
│ │ │ └─service
│ │ ├─static
│ │ └─templates
│ └─lib
├─META-INF
│ └─maven
│ └─com.example
│ └─[artifactId]
└─org
└─springframework
└─boot
└─loader
├─archive
├─data
├─jar
├─jarmode
└─util
ということで、Spring Bootで自作で組んだプログラムは、BOOT-INF\classes配下に格納される。
Tomcatを内包する実行可能jar(Fat jar)である。
Spring Boot使わないMavenプロジェクトの場合
Spring Boot使わないpureなJavaのMavenプロジェクトの場合はこのように簡素な構造になる。
jar(zip)のルートディレクトリ
├─com
│ └─example
│ ├─dto
│ └─enums
└─META-INF
└─maven
└─com.example
└─demo
他Mavenプロジェクトのpom.xmlに依存関係を追加して
import com.example.enums.Foo;
という形で参照することができる。
MANIFEST.MFについて
META-INFディレクトリ内に、MANIFEST.MFというファイルが存在する。
これはマニフェストファイルといい、jarファイルについての説明が記載されたテキストファイルであり、jarファイル作成時に自動生成される。
実行時にmain()メソッドを呼び出すクラスや、クラスパスの定義がある。
下記はその一例である。
SpringBootプロジェクトの場合の一例
Manifest-Version: 1.0
Created-By: Maven JAR Plugin 3.3.0
Build-Jdk-Spec: 17
Implementation-Title: springTest
Implementation-Version: 0.0.1-SNAPSHOT
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.example.springTest.SpringTestApplication
Spring-Boot-Version: 3.0.5
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
Spring Boot使わないMavenプロジェクトの場合の一例
Manifest-Version: 1.0
Created-By: Apache Maven 3.8.7
Built-By: circu
Build-Jdk: 17.0.5
マニフェストファイルが壊れたりしていると、jar起動したときに、
「アプリ名.jarにメイン・マニフェスト属性がありません」というエラーが出ることが考えられる。
これについては詳しくは、Spring Boot jarにメイン・マニフェスト属性がありませんを解決する方法を参照。