jar-with-dependencies
3. 嵌套方法(Jar of Jars)
還是一種辦法就是在 jar 包裡嵌套其他 jar,這個方法可以徹底避免解壓同名覆蓋的問題,但是這個方法不被 JVM 原生支持,因為 JDK 提供的 ClassLoader 僅支持裝載嵌套 jar 包的 class 文件。所以這種方法需要自定義 ClassLoader 以支持嵌套 jar。
Onejar Maven Plugin
One-JAR 就是一個基於上面嵌套 jar 實現的工具。onejar-maven-plugin 是社區基於 onejar 實現的 maven 插件。
com.jolira
onejar-maven-plugin
1.4.4
one-jar
Spring boot plugin
One-JAR 有點年久失修,好久沒有維護了,Spring Boot 提供的 Maven Plugin 也可以打包 Fatjar,支持非遮蔽和嵌套的混合模式,並且支持 maven 和 gradle 。
org.springframework.boot
spring-boot-maven-plugin
ZIP
org.jruby
jruby-complete
plugins {
id 'org.springframework.boot' version '2.0.4.RELEASE'
}
bootJar {
requiresUnpack '**/jruby-complete-*.jar'
}
requiresUnpack 參數可以定製那些 jar 不希望被解壓,採用嵌套的方式打包到 Fatjar 內部。
其打包後的內部結構為
example.jar
|
+-META-INF
| +-MANIFEST.MF
+-org
| +-springframework
| +-boot
| +-loader
| +-
+-BOOT-INF
+-classes
| +-mycompany
| +-project
| +-YourClasses.class
+-lib
+-dependency1.jar
+-dependency2.jar
應用的類文件被放置到 BOOT-INF/classes 目錄,依賴包被放置到 BOOT-INF/lib 目錄。
查看 META-INF/MANIFEST.MF 文件,其內容為
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.mycompany.project.MyApplication
啟動類是固定的 org.springframework.boot.loader.JarLauncher,應用程序的入口類需要配置成 Start-Class。這樣做的目的主要是為了支持嵌套 jar 包的類裝載,替換掉默認的 ClassLoader。
但是函數計算 Java Runtime 需要的 jar 包是一種打包結構,在服務端運行時會解壓開,./lib 目錄加到 classpath 中,單不會調用 Main-Class。所以自定義 ClassLoader 是不生效的,所以不要使用嵌套 jar 結構,除非在入口函數指定重新定義 ClassLoader 或者 classpath 以支持 BOOT-INF/classes 和 BOOT-INF/lib 這樣的定製化的類路徑。
小結
單從 Fatjar 的角度看, Spring boot maven/gradle 做得最精緻。但是 jar 包內部的自定義路徑解壓開以後和函數計算是不兼容的。所以如果用於函數計算打包,建議使用 Unshaded 或者 Shared 的打包方式,但是需要自己注意文件覆蓋問題。
寫在最後:歡迎留言討論,私信“Java”或“架構資料”有驚喜喲!加關注,持續更新!!!
閱讀更多 Java互聯網架構師 的文章