背景
java的pringboot項(xiàng)目現(xiàn)在打包方式一般會(huì)包含項(xiàng)目的所有依賴,保證每個(gè)包都能獨(dú)立部署,但缺點(diǎn)也很明顯硬毕,就是依賴稍微多點(diǎn)礼仗,就會(huì)十分大元践,對(duì)于需要頻繁更新或者多個(gè)項(xiàng)目部署的情況下,就很浪費(fèi)時(shí)間和帶寬沪羔。
其實(shí)java jar包已經(jīng)為我們提供了外置配置文件蔫饰、依賴的方案愉豺,讓開發(fā)者可以靈活選擇部署方式蚪拦,這篇文章主要講講這方面的實(shí)踐。
相關(guān)知識(shí)
Lesson: Packaging Programs in JAR Files ((oracle.com)
Apache Maven JAR Plugin – Introduction
栗子
在項(xiàng)目pom文件build下加入如下配置
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<!-- 包含文件配置盛嘿,現(xiàn)在只打包 com 文件夾 -->
<includes>
<include>
**/com/**
</include>
</includes>
<archive>
<manifest>
<!-- 配置加入依賴包 -->
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<useUniqueVersions>false</useUniqueVersions>
<!-- Spring Boot 啟動(dòng)類(自行修改) -->
<mainClass>com.server.EnterpriseApp</mainClass>
</manifest>
<manifestEntries>
<!-- 外部資源路徑加入 manifest.mf 的 Class-Path -->
<Class-Path>resources/</Class-Path>
</manifestEntries>
</archive>
<!-- jar 輸出目錄 -->
<outputDirectory>${project.build.directory}/pack/</outputDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<!-- 復(fù)制依賴 -->
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<!-- 依賴包 輸出目錄 -->
<outputDirectory>${project.build.directory}/pack/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<!-- 復(fù)制資源 -->
<executions>
<execution>
<id>copy-resources</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<!-- 資源文件 輸出目錄 -->
<outputDirectory>${project.build.directory}/pack/resources</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
第一個(gè)plugin类垦,第一個(gè)plugins就是打包我們實(shí)際的業(yè)務(wù)邏輯蚤认,不包含dependcies糕伐,其實(shí)configuration中其實(shí)就是配置目標(biāo)jar包的MANIFEST.MF文件,這個(gè)文件是我們?cè)趫?zhí)行java -jar a.jar時(shí)荣赶,java會(huì)去找這個(gè)文件來啟動(dòng)jar包,具體結(jié)構(gòu)見之上官方鏈接况增,這個(gè)插件會(huì)幫助我們把所有用到的依賴寫到文件的Class-Path :下训挡,如果目錄有要求可以通過<classpathPrefix>來指定哦澜薄。還有一塊需要注意的,就是<manifestEntries>下的<Class-Path>颊艳,這句話是單獨(dú)加入一項(xiàng)進(jìn)入Class-Path蟆沫,這個(gè)resources對(duì)應(yīng)的是我們之后單獨(dú)外置的java/resources目錄下的配置文件饭庞。
這樣,我們就能讓jar包找到需要的外置依賴绸狐。
第二塊plugin寒矿,第三個(gè)plugin這兩塊其實(shí)都是復(fù)制文件若债,復(fù)制依賴到對(duì)應(yīng)文件夾,然后復(fù)制resource
第二塊plugin 指定java版本啊终,不指定會(huì)報(bào)錯(cuò)傲须。
結(jié)論
這樣,我們打的分離包就只有100KB出頭泰讽,更新的時(shí)候就非常方便了昔期,而且多項(xiàng)目也可以共用相同的依賴硼一。但是新的問題依然很嚴(yán)重翎嫡,那就是更新依賴的時(shí)候非常不方便,需要手動(dòng)去判斷,不管是腳本檢測(cè)還是全量覆蓋圈驼,操作起來都有成本望几。
還有一種解決方案是可以部分全量橄抹,做一個(gè)公共的lib供所有項(xiàng)目調(diào)用,可以減少包體大小楼誓,用到的plugin是 maven-shade-plugin 疟羹,通過指定<excludes>來去除公共包,但是需要手動(dòng)命令行指定 通過java -classpath lib -jar a.jar來找到公共包参淫,有一定的部署前期成本愧杯,各有利弊。