3. 嵌套方法(Jar of Jars)
還是一種辦法就是在 jar 包裡嵌套其他 jar,這個方法可以徹底避免解壓同名覆蓋的問題,但是這個方法不被 JVM 原生支持,因為 JDK 提供的 ClassLoader 僅支持裝載嵌套 jar 包的 class 文件。所以這種方法需要自定義 ClassLoader 以支持嵌套 jar。
Onejar Maven Plugin
One-JAR 就是一個基於上面嵌套 jar 實現的工具。onejar-maven-plugin 是社區基於 onejar 實現的 maven 插件。
Spring boot plugin
One-JAR 有點年久失修,好久沒有維護了,Spring Boot 提供的 Maven Plugin 也可以打包 Fatjar,支持非遮蔽和嵌套的混合模式,並且支持 maven 和 gradle 。
requiresUnpack 參數可以定製那些 jar 不希望被解壓,採用嵌套的方式打包到 Fatjar 內部。
其打包後的內部結構為
應用的類文件被放置到 BOOT-INF/classes 目錄,依賴包被放置到 BOOT-INF/lib 目錄。
查看 META-INF/MANIFEST.MF 文件,其內容為
啟動類是固定的 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 這樣的定製化的類路徑。
小結
插件 構建平臺 工作機制 maven-assembly-plugin maven Unshaded Gradle Java plugin gradle Unshaded maven-shade-plugin maven Shaded com.github.johnrengelman.shadow gradle Shaded Onejar ant, maven Jar of Jars Spring boot plugin maven, gradle Unshaded, Jar of Jars 單從 Fatjar 的角度看, Spring boot maven/gradle 做得最精緻。但是 jar 包內部的自定義路徑解壓開以後和函數計算是不兼容的。所以如果用於函數計算打包,建議使用 Unshaded 或者 Shared 的打包方式,但是需要自己注意文件覆蓋問題。
閱讀更多 雲棲社區 的文章