Spring Boot 專案瘦身指南,瘦到不可思議!129M->1.3M
之前在 從使用傳統Web框架到切換到Spring Boot後的總結 中提到關於 Spring Boot 編譯打包,Spring Boot 應用程式不用額外部署到外部容器中,可以直接通過 Maven 命令將專案編譯成可執行的 jar 包,然後通過 java -jar 命令啟動即可,非常方便。
最近有小夥伴私信我說,打 jar 包方便是方便,就是每次打包出來的 jar 太大了,先不說上傳時間的問題,如果只修改了 1 個類就需要重新打包專案,然後重新上傳專案到伺服器,怎麼覺得還不如我之前使用 war 包方便呢,使用 war 包時,雖然要部署到 Tomcat 中,但只需要將修改的 class 替換一下,重啟一下 Tomcat 就可以了。。。
其實到底選擇哪種打包方式,主要還是看個人習慣和業務場景需求,畢竟 Spring Boot 也支援打包 war 包的。
今天的重點不是打包方式,而是解決困惑了小夥伴打包的 jar 太大的問題。
正常打包專案
給 Spring Boot 打包大家應該很熟了吧,只需要在 pom.xml 檔案中配置 spring-boot-maven-plugin
打包外掛:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
然後在專案根目錄執行 mvn clean pavkage
就可以完成打包了,如下是我本地的一個專案打包情況:
可以看到打包出的 jar 應用是相當的大了,如小夥伴說的一樣,如果每次修改一個 class 檔案或者配置檔案,就需要重新打包然後上傳伺服器的話,那確實是太麻煩了,可能上傳就浪費大部分時間。。。
應用瘦身(分離lib和配置檔案)
其實 jar 包大的原因在於所有的依賴包全部整合在 jar 包裡面,如下是瘦身前的 jar 包內部結構:
其中 classes 就是我們專案的程式碼,僅僅1.3M,而 129MB 的 lib 目錄是專案中所有的依賴(比如spinrg、Hibernate等依賴),如果我們能把這個 lib 目錄提取出來,整個專案就會變得特別小了。說幹就幹。
我們知道 Spring Boot 的打包終究是依賴於 Maven ,所以想到更改打包資訊,無非就是指定 Maven 的配置。
在 pom.xml 新增如下資訊(後文解釋):
<build>
<finalName>你想要的jar包名稱</finalName>
<plugins>
<!-- 1、編譯出不帶 lib 資料夾的Jar包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!--表示編譯版本配置有效-->
<fork>true</fork>
<!--引入第三方jar包時,不新增則引入的第三方jar不會被打入jar包中-->
<includeSystemScope>true</includeSystemScope>
<!--排除第三方jar檔案-->
<includes>
<include>
<groupId>nothing</groupId>
<artifactId>nothing</artifactId>
</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 2、完成對Java程式碼的編譯,可以指定專案原始碼的jdk版本,編譯後的jdk版本,以及編碼 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- 原始碼使用的JDK版本 -->
<source>${java.version}</source>
<!-- 需要生成的目標class檔案的編譯版本 -->
<target>${java.version}</target>
<!-- 字符集編碼 -->
<encoding>UTF-8</encoding>
<!-- 用來傳遞編譯器自身不包含但是卻支援的引數選項 -->
<compilerArguments>
<verbose/>
<!-- windwos環境(二選一) -->
<bootclasspath>${java.home}/lib/rt.jar:${java.home}/lib/jce.jar</bootclasspath>
<!-- Linux環境(二選一) -->
<bootclasspath>${java.home}/lib/rt.jar:${java.home}/lib/jce.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
<!-- 3、將所有依賴的jar檔案複製到target/lib目錄 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<!--複製到哪個路徑,${project.build.directory} 缺醒為 target,其他內建引數見下面解釋-->
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<!-- 4、指定啟動類,指定配置檔案,將依賴打成外部jar包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<!-- 是否要把第三方jar加入到類構建路徑 -->
<addClasspath>true</addClasspath>
<!-- 外部依賴jar包的最終位置 -->
<classpathPrefix>lib/</classpathPrefix>
<!-- 專案啟動類 -->
<mainClass>com.javam4.MyApplication</mainClass>
</manifest>
</archive>
<!--資原始檔不打進jar包中,做到配置跟專案分離的效果-->
<excludes>
<!-- 業務jar中過濾application.properties/yml檔案,在jar包外控制 -->
<exclude>*.properties</exclude>
<exclude>*.xml</exclude>
<exclude>*.yml</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
如下一一細拆如上配置:
1、spring-boot-maven-plugin
Springboot 預設使用 spring-boot-maven-plugin 來打包,這個外掛會將專案所有的依賴打入專案 jar 包裡面,正常打包時 spring-boot-maven-plugin 結構如下:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.javam4.MyApplication</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
如下是提取的修改項:
<configuration>
<!--表示編譯版本配置有效-->
<fork>true</fork>
<!--引入第三方jar包時,不新增則引入的第三方jar不會被打入jar包中-->
<includeSystemScope>true</includeSystemScope>
<!--排除第三方jar檔案-->
<includes>
<include>
<groupId>nothing</groupId>
<artifactId>nothing</artifactId>
</include>
</includes>
</configuration>
修改的作用:
- includeSystemScope:jar包分兩種,一種是spring、mybatis等這種專案依賴的,再就是我們外部手動引入的第三方 jar 依賴,如果該引數不設定為 true 的話是不能被打包進來的~
- includes:這個節點就是排除專案中所有的 jar,那還怎麼打包?
其實我們需要將打包外掛替換為 maven-jar-plugin,然後使用該外掛拷貝依賴到 jar 到外面的 lib 目錄。
2、maven-xxx-plugin
從 2、3、4 你會發現用到了 maven-xxx-plugin 格式的三種外掛,簡單說一下這三者的作用:
-
maven-compiler-plugin:
完成對Java程式碼的編譯,可以指定專案原始碼的jdk版本、編譯後的jdk版本,以及編碼,如果不寫這個外掛也是沒問題的,不寫會使用預設的 jdk 版本來處理,只是這樣容易出現版本不匹配的問題,比如本地maven環境用的3.3.9版本,預設會使用jdk1.5進行編譯,而專案中用的jdk1.8的編譯環境,那就會導致打包時編譯不通過。
-
maven-dependency-plugin:
作用就是將所有依賴的jar檔案複製到指定目錄下,其中涉及到的
${project.xx}
見下文補充。 -
maven-jar-plugin:
主要作用就是將maven工程打包成jar包。
主要說一下 maven-jar-plugin 外掛的如下配置:
<configuration>
<!--資原始檔不打進jar包中,做到配置跟專案分離的效果-->
<excludes>
<!-- 業務jar中過濾application.properties/yml檔案,在jar包外控制 -->
<exclude>*.properties</exclude>
<exclude>*.xml</exclude>
<exclude>*.yml</exclude>
</excludes>
</configuration>
打包時排除資源配置檔案,如果排除了配置檔案那麼專案啟動是怎麼讀取呢?
配置檔案有這麼一個預設的優先順序:
當前專案config目錄下
> 當前專案根目錄下
> 類路徑config目錄下
> 類路徑根目錄下
因此只需要將配置檔案複製一份到與 jar 包平級目錄下,或者與jar包平行config目錄下,就能優先使用此配置檔案,達到了偽分離目的。
最終的目錄結構如下:
Maven 中的內建變數說明:
${basedir}
專案根目錄${project.build.directory}
構建目錄,預設為target${project.build.outputDirectory}
構建過程輸出目錄,預設為target/classes${project.build.finalName}
產出物名稱,預設為{project.artifactId}-${project.version}${project.packaging}
打包型別,預設為jar${project.packaging}
打包型別,預設為jar${project.xxx}
當前pom檔案的任意節點的內容
瘦身總結
Spring Boot 框架提供了一套自己的打包機制 — spring-boot-maven-plugin,Springboot 預設使用該外掛來打包,打包時會將專案所有的依賴打入專案 jar 包裡面,如果我們想要抽離依賴的 jar 僅僅使用該外掛是不行的,就需要將打包外掛替換為 maven-jar-plugin,並拷貝所有的依賴到 jar 外面的 lib 目錄。
專案打包時,在分離依賴 jar 包基礎上,我們又排除了配置檔案,因為配置檔案有一個預設的讀取路徑:
當前專案config目錄下
> 當前專案根目錄下
> 類路徑config目錄下
> 類路徑根目錄下
我們只需要在當前專案 jar 包同級目錄建立一個 config 資料夾,然後將配置檔案複製一份,這樣就達到了偽分離目的。
之後再修改配置檔案,比如埠號、資料庫連線資訊等,就不需要重新打包專案了,直接修改完配置檔案重啟專案就可以了。
而經過分離依賴後的 jar 包從原來的100多兆到現在的1兆,如果後面需要變更業務邏輯,只需要輕量的編譯專案,快速的實現專案的上傳替換,有效的減少了網路開銷,提高專案部署的效率。
部落格地址:https://niceyoo.cnblogs.com
更多原創內容可以移步我的公眾號,回覆「面試」獲取我整理的2020面經。
相關推薦
Spring Boot 專案瘦身指南,瘦到不可思議!129M->1.3M
之前在 從使用傳統Web框架到切換到Spring Boot後的總結 中提到關於 Spring Boot 編譯打包,Spring Boot 應用程式不用額外部署到外部容器中,可以直接通過 Maven 命令將專案編譯成可執行的 jar 包,然後通過 java -jar 命令啟動即可,非常方便。 最近有小夥伴私信我
Spring boot專案剛搭建好,啟動測試,出現Failed to configure a DataSource
今天新搭建了一個springboot+gradle框架,然而,剛搭建好執行的時候,就報了一個錯誤: Error starting ApplicationContext. To display the conditions report re-r
Spring Boot專案生成jar包,並在windows伺服器中註冊成服務,開機啟動
最近工作在windows伺服器上部署 spring boot 的jar包之前都是在linux上執行命令: nohup java -jar xxx.jar > xxx.log & 現在為了達到跟Linux一樣的效果。最終方案:使用winswwinsw是一個開源
spring boot專案啟動報錯,找不到XXX類
不是很懂csdn如何提問,所以先記錄下來,也希望知道解決方案的能給點提示。問題描述: 新建一個spring boot工程,並且有如下專案: 專案一:cust-service,有啟動類CustApplication、有依賴一個base服務(base沒有applica
如何在spring boot 專案中加入freemarker,以及使用yaml語法時的注意事項
最近在做一個用郵件傳送報表的專案,要求在郵件正文中將excel表格顯示出來。我考慮到通過字串拼接表格太麻煩,而且不利於維護,所以使用freemarker做郵件模板來做展示。 專案環境:spring boot 構建工具:maven 步驟如下: 1.引入pom依賴
Spring Boot 把 Maven 幹掉了,擁抱 Gradle!
在國外某社交網站上有一個關於遷移 Spring Boot 遷移 Maven 至 Gradle 的帖子: ![](https://img2020.cnblogs.com/other/1218593/202006/1218593-20200617101444432-613256673.png) 該貼子上也有很
Spring Boot Redis 實現分散式鎖,真香!!
之前看很多人手寫分散式鎖,其實 Spring Boot 現在已經做的足夠好了,開箱即用,支援主流的 Redis、Zookeeper 中介軟體,另外還支援 JDBC。 本篇棧長以 Redis 為例(這也是用得最多的方案),教大家如何利用 Spring Boot 整合 Redis 實現快取,如何簡單、快速實現
Spring Boot 2.4 正式釋出,重大調整!!!
大家週末愉快啊,[Spring Boot 2.3.5](https://mp.weixin.qq.com/s/BhNofKQRVRBp82AOJgjctw) 沒釋出幾天,你看,還是 1 周前釋出的: ![](https://img2020.cnblogs.com/other/1218593/202011/1
Redis “瘦身”指南
格式 block reac etime toc z-index 回收 url key-value 前言 Redis 應該是開發者最常用的緩存服務器了,它豐富的數據結構,快速高效的內存操作能幫助開發者迅速完成復雜功能的設計,可以說讓人一旦使用過後很難再離開它了,甚至在一
【spring cloud】匯入一個新的spring boot專案作為spring cloud的一個子模組微服務,怎麼做/或者 每次匯入一個新的spring boot專案,IDEA不識別子module,啟動類無法啟動/右下角沒有藍色圖示
如題:匯入一個新的spring boot專案作為spring cloud的一個子模組微服務,怎麼做 或者說每次匯入一個新的spring boot專案,IDEA不識別,啟動類無法啟動,怎麼解決 下面一起來走一遍這個流程: 1.將一個spring boot服務匯入spring cloud中作為一個子模組
spring boot 專案 ,spring data jpa 初使用
我使用的是 maven 構建工具,使用 spring data jpa 來實現簡單的使用者資料增刪改查功能。 專案使用: spring boot、spring data jpa、mysql。 專案使用 postman 工具來測試功能是否實現。 程式碼 pom.xml 如下:
APK瘦身優化,減小apk的大小
首先通過Android Studio自帶的工具分析我們的apk 這樣我們就可以很清楚地看到我們的apk中最大一部分是誰,點選對應項就可以檢視它的具體內容,如下圖 這裡我們可以詳細的看到apk中用到的所有的相關庫,可以根據自己的實際情況進行刪減,比如:我在壓縮
教你搭建Spring Boot專案,包會!
目錄 前言 開始搭建最簡單的Spring Boot工程(下文會延伸) 第一步:開啟IDEA,新建專案 第二步:選擇Spring Initializr 第三步:設定專案基本資訊 第四步:為專案選擇依賴 第五步:建立專案資料夾 &
spring boot專案 前臺介面動態新增div,以及特定點選div事件,delegate()方法。
因為是初次寫前臺介面,在有些地方遇到了很多的問題,其中就包括著後臺得到List,在前臺玄幻div顯示介面,接收資料。一下是迴圈顯示的程式碼。 <!DOCTYPE html> <html lang="en" xmlns:th="http://www.thym
在spring boot 專案中使用thymeleaf模板,將後臺資料傳遞給前臺介面。
1、將後臺資料傳遞給前臺有很多種方式,可以將後臺要傳遞的資料轉換成json格式,去傳遞給前臺,也可以通過model形式去傳遞出去,這篇部落格主要是使用thymeleaf模板,將後臺資料傳遞給前臺。 2、首先要在spring boot 專案中新增如下依賴:
建立spring-boot專案,學習(一)
一、用IDEA建立spring-boot工程 IDEA版本:2018.1.5的Ultimate版本,非Ultimate版本可能缺少一些功能。 下面開始建立spring-boot專案 1,選擇Spring-Initializer,之後next 2,填寫專案名稱,專案
在Eclipse中如何將spring boot專案打成的jar包,並且雙擊執行cmd 執行jar包,設定開機啟動
1、如何在eclipse中將spring boot專案打成jar包 1.右擊專案,選擇Run As - Maven clean 2.右擊專案,選擇Run As - Maven install 3.成功後 會在專案的target資料夾下生成jar包 2、直接雙擊執行cm
spring boot 專案打包,配置構建外掛
Spring Boot:jar中沒有主清單屬性 使用Spring Boot微服務搭建框架,在eclipse和Idea下能正常執行,但是在打成jar包部署或者直接使用java -jar命令的時候,提示了xxxxxx.jar中沒有主清單屬性: D:\hu-git\spr
Spring Boot專案與Docker整合完成打包,打映象及推送至映象庫的功能
Spring Boot與Docker整合完成一站式打包到推送至映象庫,減少部署的過程,下面主要來介紹一下,如何整合Docker: 1.在Spring Boot專案的pom.xml檔案中做以下配置: <build> <plugins> &l
如何使用maven打包spring boot專案,打成jar包
如果你使用的是maven來管理專案,執行以下命令即可cd 專案跟目錄(和pom.xml同級) mvn clean package ## 或者執行下面的命令 ## 排除測試程式碼後進行打包 mvn clean package -Dmaven.test.skip=true也可以