SpringBoot瘦身


1.介紹

本教程中,我們將研究如何使用spring-boot-thin-launcher項目來將Spring Boot項目瘦身
Spring Boot出了名的把所有依賴打包成單個可執行的Fat JAR,同時也被廣泛應用於微服務。有時候和Fat JAR不一致的是,反復包括相同的依賴會成為一種資源浪費。

2.先決條件

首先,我們當然需要一個Spring Boot項目。在本文中,我們將研究Maven構建和Gradle構建的最常見配置。
這里是不可能覆蓋所有構建系統和相應的配置,但是希望我們能夠有常用的構建系統配置以便參考。

2.1 Maven 項目

用Maven 構建一個Spring Boot 項目,我們首先要在pom.xml或者它的parent等任何一個祖先添加Spring Boot的Maven插件:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>    
</plugin>

在這里,我們指的是插件的版本2.3.0.RELEASE,這是編寫本文時的最新版本。Spring Boot所用的依賴版本通常是用BOM或者從父的POM繼承的了:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.0.RELEASE</version>
    <relativePath/>
</parent>

2.2 Gradle 項目

用Gradle構建Spring Boot項目,我們會有相應的Gradle插件

buildscript {
    ext {
        springBootPlugin = 'org.springframework.boot:spring-boot-gradle-plugin'
        springBootVersion = '2.3.0.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("${springBootPlugin}:${springBootVersion}")
    }
} 
// elided
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
springBoot {
    mainClassName = 'DemoApplication'
}

請注意,本文只考慮Spring Boot 2.x或者更高的版本,Thin Launcher也支持舊的版本,但是可能有稍微不同的版本,具體請查看項目的主頁。

3.怎么創建一個Thin Jar

Spring Boot Thin Launcher是一個比較小的類庫,它從打包的文件中讀取項目工程的依賴關系,然后從maven倉庫下載這些依賴,最后啟動應用程序。所以在第一次啟動下載相應依賴的時候會消耗一定的時間。
所以,當我們用庫構建一個項目時,我們會得到一個包含代碼的JAR文件,一個包含依賴關系的文件,以及執行入口的主類。
當然,事情會比我們簡單的解析微妙得多,本文下面會繼續探討。

4.基本用法

現在讓我們看下如何構建一個thin jar的Spring Boot 項目。
我們將使用通常的java -jar 啟動應用程序,並使用可選的附加命令行參數來控制 Thin Launcher。
我們將在以下部分中看到其中使用參數的幾個例子; 該項目的主頁包含完整參數列表。

4.1 Maven 項目

在Maven項目中,我們必須修改SpringBoot的插件,添加相應的依賴:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot.experimental</groupId>
            <artifactId>spring-boot-thin-layout</artifactId>
            <version>1.0.23.RELEASE</version>
        </dependency>
    </dependencies>
</plugin>

Thin Launcher將會從Maven存儲在JAR下的META-INF/maven目錄中生成的pom.xml文件讀取依賴關系。
我們像往常一樣執行構建就行,例如使用 mvn install
如果我們需要同時打包fat jarthin jar,我們可以在maven的profile中定義springboot插件。

4.2 Maven依賴:thin.properties

除了pom.xml之外,我們也可以讓maven生產thin.properties。在這種情況下,該文件會包含完整的依賴列表,包括可傳遞的依賴列表,但是相對pom.xml來說,thin Launcher對thin.properties更加友好。
默認情況下,插件在src/main/resources/META-INF中輸出thin.properties,但是我們可以用thin.output屬性來指定它的位置:

mvn org.springframework.boot.experimental:spring-boot-thin-maven-plugin:properties -Dthin.output=.

4.3 Gradle項目

不同的是,在Gradle項目中,我們需要添加了一個專用的插件:

buildscript {
    ext {
        //...
        thinPlugin = 'org.springframework.boot.experimental:spring-boot-thin-gradle-plugin'
        thinVersion = '1.0.23.RELEASE'
    }
    //...
    dependencies {
        //...
        classpath("${thinPlugin}:${thinVersion}")
    }
}
//elided
apply plugin: 'maven'
apply plugin: 'org.springframework.boot.experimental.thin-launcher'

為了獲取thin jar, 我們需要執行 thinJar 任務:

./gradlew thinJar

4.4 Graldle依賴:pom.xml

在前一小節的代碼示例中,除了Thin Launcher之外,我們還聲明了Maven插件(我們已經事先看到Spring Boot的依賴管理插件)
這是因為和我們之前的Maven案例一樣,打包后的文件包含了一個pom.xml來列舉應用程序所需要的依賴關系。pom.xml文件是由thinPom任務生成。 我們可以用專門的一個任務來定制生成pom.xml, 在這里,我們復制下插件已經做的東西:

task createPom {
    def basePath = 'build/resources/main/META-INF/maven'
    doLast {
        pom {
            withXml(dependencyManagement.pomConfigurer)
        }.writeTo("${basePath}/${project.group}/${project.name}/pom.xml")
    }
}

為了使用我們的自定義pom.xml文件,我們將上述任務添加到jar任務的依賴項中:

bootJar.dependsOn = [createPom]

4.5 Gralde依賴:thin.properties

和前面的maven項目一樣,我們也可以讓Gradle生成thin.properties而不是pom.xml, 生成thin.properties文件的任務叫做thinProperties,默認情況下是不使用它的。我們也可以把它添加到任務的依賴中:

bootJar.dependsOn = [thinProperties]

5.保存依賴

thin jar的目的是為了避免依賴項和應用程序綁在一起,然后依賴是不會消失的,這些依賴只是存儲在其他地方而已。
特別地,Thin Launcher是使用maven的基礎架構來解決依賴的,所以:

  • 會檢查本地的Maven倉庫,默認是指 ~/.m2/repository,當然也可以移到其他地方。
  • 會從maven中央倉庫中下載缺失的依賴
  • 最后會緩存所下載的依賴到本地maven倉庫中,下次啟動的時候就不會再繼續下載了。

當然,下載依賴階段是比較緩慢而且容易出錯的部分,主要是因為是通過網絡訪問maven中央倉庫來下載依賴,總之這些是不可靠的。
幸運的是,有很多種方式將依賴和應用程序一起部署,例如可以預打包在容器中。

5.1 運行預熱的程序

緩存依賴的最簡單方法就是在目標環境中對程序進行預熱運行。正如前面所說的,預熱運行會把所依賴的文件緩存到本地的maven倉庫中去。如果我們運行了多個應用程序,maven倉庫中已經飽和了所依賴的庫的話,就沒有必要重復下載了。
由於運行應用程序可能會導致不必要的副作用,我們還可以執行“試運行”,它只解析和下載依賴項,而不運行任何用戶代碼:

java -Dthin.dryrun=true -jar my-app-1.0.jar

5.2 在構建的時候打包依賴

另外一個選擇就是在構建的時候打包依賴,當然,這不是把依賴打包到JAR中,然后我們可以復制這些依賴到目標的環境中。
通常這會更加簡單,因為沒必要在目標環境中運行應用程序。但是,如果我們部署多個環境,就必須手動或用腳本合並他們的依賴關系。
在構建過程中,Maven和Gradle的Thin 插件打包的依賴格式與maven的本地倉庫是一樣的:

root/
    repository/
        com/
        net/
        org/
        ...

實際上,我們還可以在運行的時候使用 thin.root參數來指定依賴的目錄:

$ java -jar my-app-1.0.jar --thin.root=my-app/deps

5.3 用maven打包依賴

為了能讓maven幫我們打包依賴,我們需要添加 spring-boot-thin-maven插件

<plugin>
    <groupId>org.springframework.boot.experimental</groupId>
    <artifactId>spring-boot-thin-maven-plugin</artifactId>
    <version>${thin.version}</version>
    <executions>
        <execution>
        <id>resolve</id>
        <goals>
            <goal>resolve</goal>
        </goals>
        <inherited>false</inherited>
        </execution>
    </executions>
</plugin>

構建項目后,我們將找到一個目錄target/thin/root/會出現上一節討論的結構。

5.4 用Gradle打包依賴

如我們用_thin-launcher_插件,我們會有_thinResolve_任務可以用。這個任務會保存應用和它的依賴在_build/thin/root/_ 目錄中,跟maven的一樣:

gradlew thinResolve

6.總結和進一步閱讀

在這篇文章中,我們學習了如何制作Spring Boot的thin jar,同時也看到了如何使用maven的架構來下載和存儲應用的依賴關系。
項目主頁 也有一些其他的使用指導,好比如一些命令參數等。

微信關注我,發現更多java領域知識
JFound


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM