利用spring-boot-thin-launcher插件分離jar包的依賴和配置

Spring Boot項目可以通過spring-boot-maven-plugin插件打包生成一個可執(zhí)行的jar包先誉,這樣可以脫離web容器(例如tomcat)直接運行。但默認(rèn)情況下spring-boot-maven-plugin打出來的包是一個fat jar,即將所有的依賴全部打進了jar包當(dāng)中婉商,這樣的jar包體積很大晶通,每次更新系統(tǒng)的時候都需要完整替換整個jar包(本地還好,如果是云服務(wù)器华望,網(wǎng)速慢了每次上傳文件都想砸電腦π__π)蕊蝗。此外,系統(tǒng)切換環(huán)境時赖舟,也同時需要切換配置參數(shù)蓬戚,雖然可以使用配置中心或者利用命令行參數(shù)修改配置,但有時候也免不了直接需要修改配置文件宾抓,這樣的話就有必要將配置文件從jar包中分離出來子漩,單獨存放。

Spring社區(qū)大概也考慮到了部分開發(fā)者有這樣的需求石洗,所以提供了spring-boot-thin-launcher這個插件用來將項目的依賴和配置從jar包中分離出去幢泼。這個插件雖然是放到spring-projects-experimental(意思就是實驗性質(zhì)的項目)當(dāng)中的,但從我使用的經(jīng)驗來看應(yīng)該是比較穩(wěn)定的讲衫,能夠滿足絕大部分場景的需求旭绒。廢話少說,還是先上代碼吧:

<build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <configuration>
                    <!--項目的執(zhí)行入口-->
                    <mainClass>com.example.Application</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.springframework.boot.experimental</groupId>
                        <artifactId>spring-boot-thin-layout</artifactId>
                        <version>1.0.12.RELEASE</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot.experimental</groupId>
                <artifactId>spring-boot-thin-maven-plugin</artifactId>
                <version>1.0.12.RELEASE</version>
                <executions>
                    <execution>
                        <!--在編譯時下載依賴包 -->
                        <id>resolve</id>
                        <goals>
                            <goal>resolve</goal>
                        </goals>
                        <inherited>false</inherited>
                    </execution>
                </executions>
            </plugin>
            <!--移動配置文件到外部文件夾-->
            <plugin>
                <artifactId>maven-antrun-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <tasks>
                                <move file="${project.build.directory}/classes/application.yml" todir="${project.build.directory}/thin/root/config"/>
                                <copy todir="${project.build.directory}/thin/root/">
                                    <fileset dir="${basedir}/bin"/>
                                </copy>
                            </tasks>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

在maven-antrun-plugin中可以根據(jù)需要定義一些額外的任務(wù)焦人,比如移動其它的配置文件挥吵,或者將外部的一些文件加入到項目目錄中(比如執(zhí)行腳本等)。
這樣配置后花椭,打包以后的target目錄大概是這樣的:


target目錄結(jié)構(gòu).png

其中thin目錄下面就可以作為整個項目的部署目錄了忽匈,config是配置文件的存放目錄,respository下面是所有的依賴包矿辽,backend-2.0.jar中僅包含了項目自身的資源丹允,體積比之前小太多了。

運行原理

那為什么執(zhí)行時袋倔,系統(tǒng)知道自動去外部加載依賴和配置呢雕蔽?這個問題需要首先了解打包后的結(jié)構(gòu),把backend-2.0.jar解壓之后宾娜,會發(fā)現(xiàn)除了我們自己的類和資源以外批狐,還多了一個類:
org.springframework.boot.loader.wrapper.ThinJarWrapper,其實我們在運行項目時,這個類才是真正的項目入口嚣艇,它會在默認(rèn)位置查找項目相關(guān)的依賴承冰,如果沒有找到,甚至還會從指定的maven倉庫中直接下載食零,所以啟動時系統(tǒng)能夠識別到外部的依賴包困乒。至于外部配置,是因為Spring Boot框架在讀取配置文件時贰谣,會默認(rèn)讀取幾個目錄下的配置文件娜搂,其中優(yōu)先級最高的就是當(dāng)前目錄下的config目錄(所以config目錄的名字不能改成其它的)。

執(zhí)行jar包的時候需要注意吱抚,要額外添加一個參數(shù)來指定依賴包所在的倉庫位置(在我們的配置中就在jar包的當(dāng)前文件夾)涌攻,例如:-Dthin.root=. 默認(rèn)的位置是${user.home}/.m2,如果倉庫中沒有需要的依賴频伤,啟動jar包時還會自動連接遠程倉庫進行下載,導(dǎo)致啟動時間非常長芝此,這一點需要注意憋肖。spring-boot-thin-launcher還有很多可配置的參數(shù),具體可以到 官網(wǎng) 上自行查看婚苹。

另外附上一個通用的spring-boot-thin-launcher打包文件的啟動腳本:

#!/bin/bash
#這里指定需要運行的jar包的名字
APP_NAME="your-jar-name.jar"
JVM_ARGS="-Xms512M -Xmx2048M -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/log/heap.hprof"
THIN_ARGS="-Dthin.root=. -Dthin.offline=true"
#使用說明岸更,用來提示輸入?yún)?shù)
usage() {
    echo "Usage: sh 執(zhí)行腳本.sh [start|stop|restart|status|run]"
    exit 1
}
 
#檢查程序是否在運行
is_exist(){
  pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}' `
  #如果不存在返回1,存在返回0
  if [ -z "${pid}" ]; then
   return 1
  else
    return 0
  fi
}
 
#后臺啟動
start(){
  is_exist
  if [ $? -eq "0" ]; then
    echo "${APP_NAME} is already running. pid=${pid} ."
  else
    echo "${APP_NAME} running with args: nohup java $THIN_ARGS -jar $JVM_ARGS $APP_NAME "
    nohup java $THIN_ARGS -jar $JVM_ARGS $APP_NAME >> catalina.out 2>&1 &
  fi
}
#前臺啟動
run(){
  is_exist
  if [ $? -eq "0" ]; then
    echo "${APP_NAME} is already running. pid=${pid} ."
  else
    echo "${APP_NAME} running with args: java $THIN_ARGS -jar $JVM_ARGS $APP_NAME"
    java $THIN_ARGS -jar $JVM_ARGS $APP_NAME 
  fi
}
 
#停止方法
stop(){
  is_exist
  if [ $? -eq "0" ]; then
    kill -9 $pid
  else
    echo "${APP_NAME} is not running"
  fi
}
 
#輸出運行狀態(tài)
status(){
  is_exist
  if [ $? -eq "0" ]; then
    echo "${APP_NAME} is running. Pid is ${pid}"
  else
    echo "${APP_NAME} is NOT running."
  fi
}
 
#重啟
restart(){
  stop
  start
}
 
#根據(jù)輸入?yún)?shù)膊升,選擇執(zhí)行對應(yīng)方法怎炊,不輸入則執(zhí)行使用說明
case "$1" in
  "start")
    start
    ;;
  "run")
    run
    ;;
  "stop")
    stop
    ;;
  "status")
    status
    ;;
  "restart")
    restart
    ;;
  *)
    usage
    ;;
esac
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市廓译,隨后出現(xiàn)的幾起案子评肆,更是在濱河造成了極大的恐慌,老刑警劉巖非区,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瓜挽,死亡現(xiàn)場離奇詭異,居然都是意外死亡征绸,警方通過查閱死者的電腦和手機久橙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來管怠,“玉大人淆衷,你說我怎么就攤上這事〔吵冢” “怎么了祝拯?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長她肯。 經(jīng)常有香客問我鹿驼,道長欲低,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任畜晰,我火速辦了婚禮砾莱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘凄鼻。我一直安慰自己腊瑟,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布块蚌。 她就那樣靜靜地躺著闰非,像睡著了一般。 火紅的嫁衣襯著肌膚如雪峭范。 梳的紋絲不亂的頭發(fā)上财松,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天,我揣著相機與錄音纱控,去河邊找鬼辆毡。 笑死,一個胖子當(dāng)著我的面吹牛甜害,可吹牛的內(nèi)容都是我干的舶掖。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼尔店,長吁一口氣:“原來是場噩夢啊……” “哼眨攘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起嚣州,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤鲫售,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后该肴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霜医,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡瘟檩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歌溉。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡舀患,死狀恐怖贪惹,靈堂內(nèi)的尸體忽然破棺而出媳维,到底是詐尸還是另有隱情,我是刑警寧澤铸抑,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布贡耽,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蒲赂。R本人自食惡果不足惜阱冶,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望滥嘴。 院中可真熱鬧木蹬,春花似錦、人聲如沸若皱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽走触。三九已至晦譬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間互广,已是汗流浹背敛腌。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留惫皱,地道東北人像樊。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像逸吵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子缝裁,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,647評論 2 354