SpringBoot迭代發(fā)布下的Jar瘦身實(shí)踐
點(diǎn)擊關(guān)注公眾號(hào),實(shí)用技術(shù)文章及時(shí)了解
作者:集成顯卡
blog.csdn.net/ssrc0604hx/article/details/54175027
背景
隨著Spring Boot的流行,越來越多開發(fā)者選擇使用Spring Boot來發(fā)布Web應(yīng)用。不同于傳統(tǒng)的War包發(fā)布,Spring Boot把整個(gè)項(xiàng)目打包成一個(gè)可運(yùn)行的Jar包(即所謂的Flat Jar),導(dǎo)致了這個(gè)Jar包很大(通常有40M+)。如今迭代發(fā)布時(shí)常有的事情,每次都上傳一個(gè)如此龐大的文件,會(huì)浪費(fèi)很多時(shí)間。
下面就以一個(gè)小項(xiàng)目為例,簡(jiǎn)述小弟所用的瘦身方案。當(dāng)然如果是內(nèi)網(wǎng)發(fā)布或者你用的寬帶異常給力,瘦身就沒有多大意義了。
實(shí)踐
項(xiàng)目簡(jiǎn)介
新建一個(gè)練習(xí)用的項(xiàng)目,其結(jié)構(gòu)如下

ht-cdn存放的是靜態(tài)資源(如第三方j(luò)s、css、images等)ht-domain項(xiàng)目中的數(shù)據(jù)實(shí)體定義ht-repository數(shù)據(jù)層接口及實(shí)現(xiàn)ht-service業(yè)務(wù)邏輯接口及實(shí)現(xiàn)ht-ui-webWeb管理
其中ht-ui-web依賴于ht-domain、ht-repository、ht-service,實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的GetMapping。
接著打包項(xiàng)目,整個(gè)jar包24M這樣

瘦身準(zhǔn)備
首先我們要對(duì)Jar包有一個(gè)初步認(rèn)識(shí),它的內(nèi)部結(jié)構(gòu)如下
example.jar
|
+-META-INF
| +-MANIFEST.MF
+-org
| +-springframework
| +-boot
| +-loader
| +-<spring boot loader classes>
+-BOOT-INF
+-classes
| +-mycompany
| +-project
| +-YourClasses.class
+-lib
+-dependency1.jar
+-dependency2.jar
運(yùn)行該Jar時(shí)默認(rèn)從BOOT-INF/classes加載class,從BOOT-INF/lib加載所依賴的Jar包。如果想要加入外部的依賴Jar,可以通過設(shè)置環(huán)境變量LOADER_PATH來實(shí)現(xiàn)。
如此一來,就可以確認(rèn)我們的思路了:
把那些不變的依賴Jar包(比如spring依賴、數(shù)據(jù)庫Driver等,這些在不升級(jí)版本的情況下是不會(huì)更新的)從Flat Jar中抽離到單獨(dú)的目錄,如libs 在啟動(dòng)Jar時(shí),設(shè)置LOADER_PATH使用上一步的libs
這樣,我們最終打包的jar包體積就大大減少,每次迭代后只需要更新這個(gè)精簡(jiǎn)版的Jar即可。
具體步驟
打包時(shí)瘦身
通常我們是用spring-boot-maven-plugin進(jìn)行打包,通過閱讀文檔發(fā)現(xiàn)可以通過配置使得該插件在打包時(shí)忽略特定的依賴,文檔在spring-boot-maven-plugin。
首先備份一下原先的依賴:編譯打包成Flat Jar,然后將BOOT-INF/lib下的除去ht-*相關(guān)的jar文件全部解壓出來,另存到libs目錄下。
接著修改pom.xml配置如下
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layout>ZIP</layout>
<!--去除在生產(chǎn)環(huán)境中不變的依賴-->
<excludeGroupIds>
org.springframework.boot,
org.springframework,
org.springframework.data,
org.mongodb,
com.github.0604hx,
com.fasterxml.jackson.core,
commons-beanutils,
commons-codec,
org.apache.commons,
org.apache.tomcat.embed,
org.hibernate,
org.slf4j,
com.jayway,
org.jboss,
com.alibaba,
com.fasterxml,
commons-collections,
ch.qos.logback,
org.scala-lang,
org.yaml,
org.jboss.logging,
javax.validation,
nz.net.ultraq.thymeleaf,
org.thymeleaf,
ognl,
org.unbescape,
org.javassist
</excludeGroupIds>
</configuration>
</plugin>
</plugins>
</build>
此時(shí)打包好的ht-ui-web.jar只有117kb這樣

BOOT-INF/lib下只有ht相關(guān)的jar

但是由于沒有其他依賴,ht-ui-web.jar是不能如期運(yùn)行起來的
java -jar ht-ui-web-1.0.jar
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:521)
Caused by: java.lang.NoClassDefFoundError: org/springframework/boot/SpringApplication
at com.nerve.huotong.web.WebApplication.main(WebApplication.java:21)
... 8 more
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.SpringApplication
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:94)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 9 more
至此我們要設(shè)置LOADER_PATH,如下
java -Dloader.path="libs/" -jar ht-ui-web.jar
便可以看到熟悉的Spring Boot 啟動(dòng)信息了。
繼續(xù)瘦身
上面的項(xiàng)目結(jié)構(gòu)介紹提到了ht-cdn,我是把前端用到的庫都放在這里。然后單獨(dú)啟動(dòng)一個(gè)Web Application。其他項(xiàng)目需要用到靜態(tài)資源就直接使用。
還有另外一個(gè)做法是,把resources/public直接丟到libs下(就是跟上一步剝離出來的jar包放在一起),結(jié)構(gòu)如下:

這樣也是可以的(不過要注意不能跟真實(shí)項(xiàng)目中自己寫的靜態(tài)資源重名)。
結(jié)語
經(jīng)過上面的瘦身,每次迭代開發(fā)開的Jar包就顯得苗條多了。
插些題外話
Spring Boot 中的banner.txt
banner是spring boot 應(yīng)用啟動(dòng)時(shí)打印在控制臺(tái)的彩蛋信息,默認(rèn)是這樣的
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.4.3.RELEASE)
想要修改這個(gè)文本的話,只需要在resources下新建banner.txt即可。
這里可以自定義banner:
http://patorjk.com/software/taag/

