如何解決項(xiàng)目中的fat jar

方案:通過拆分模塊和使用 provided 作用域優(yōu)化 SDK 和 API 的依賴

背景:

你們項(xiàng)目的 fat JAR 問題主要集中在 API 和 SDK 包里。通過將 SDK 和 API 進(jìn)行模塊化,并且合理使用 Maven 的 provided 作用域,可以避免不必要的依賴被打包到最終的 JAR 文件中,從而解決 fat JAR 問題。

1. 模塊化項(xiàng)目結(jié)構(gòu):將 SDK 和 API 拆分為獨(dú)立模塊

目標(biāo):通過模塊化管理 SDK 和 API,確保每個(gè)模塊只包含必要的代碼和依賴,不將所有依賴都打包在同一個(gè) JAR 文件中。

步驟

  • 拆分 SDK 和 API 為獨(dú)立模塊:你可以將 SDK 和 API 分別拆分為獨(dú)立的 Maven 模塊,分別負(fù)責(zé)自己的功能。這樣,SDK 模塊可以單獨(dú)發(fā)布,而 API 模塊僅用于定義接口和通用服務(wù),不包含實(shí)現(xiàn)代碼。

  • API 模塊:只包含 API 的定義(接口、DTO 等),不包含實(shí)現(xiàn)。這個(gè)模塊將作為 SDK 模塊的依賴。

  • SDK 模塊:包含 SDK 的實(shí)現(xiàn),依賴于 API 模塊。

目錄結(jié)構(gòu)示例

my-project
│
├── api                 # API 模塊
│   ├── src
│   └── pom.xml
│
└── sdk                 # SDK 模塊
    ├── src
    └── pom.xml

Maven 配置示例

  • API 模塊(api/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>com.example</groupId>
    <artifactId>api</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>
    
    <dependencies>
        <!-- No external dependencies needed here, just API definitions -->
    </dependencies>
</project>
  • SDK 模塊(sdk/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>sdk</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>
    
    <dependencies>
        <!-- SDK depends on the API module -->
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>api</artifactId>
            <version>1.0.0</version>
        </dependency>

        <!-- External dependencies such as Spring, Servlet API -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope> <!-- Container provides this -->
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.10</version>
            <scope>provided</scope> <!-- Provided by external environment -->
        </dependency>
    </dependencies>
</project>

解釋:

  • 拆分模塊:通過將 SDK 和 API 拆分為獨(dú)立模塊,SDK 模塊只依賴 API 模塊,避免了所有依賴都被打包在同一個(gè) JAR 文件中的問題。
  • 減少不必要的依賴:只將 SDK 和 API 需要的依賴包含在 SDK 模塊中,并將這些依賴的 scope 設(shè)置為 provided,避免它們被打包進(jìn) SDK JAR 中。

2. 使用 provided 作用域來優(yōu)化 SDK 和 API 依賴

目標(biāo):確保在編譯和測試時(shí)需要的依賴,在打包時(shí)不會被包含在最終的 JAR 文件中。

步驟

  • 標(biāo)記容器提供的依賴:對于那些由外部容器或環(huán)境提供的依賴(例如 Servlet API、JSP、Spring),使用 provided 作用域來標(biāo)記它們。

  • SDK 中使用 provided 作用域:如果你的 SDK 依賴于一些框架(如 Spring 或 Servlet API),并且這些框架在運(yùn)行時(shí)已經(jīng)由外部容器提供,那么這些依賴應(yīng)設(shè)置為 provided,這樣就不會被打包進(jìn) JAR 文件中。

示例配置
在 SDK 模塊中:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope> <!-- Servlet API 由容器提供 -->
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.10</version>
    <scope>provided</scope> <!-- Spring 由應(yīng)用服務(wù)器提供 -->
</dependency>

解釋:

  • provided 作用域:表示這些依賴只在編譯時(shí)可用,運(yùn)行時(shí)由外部容器提供。這樣,它們不會被打包進(jìn) SDK 模塊的 JAR 文件中。

  • 減少 fat JAR 大小:通過使用 provided 作用域,容器提供的依賴(如 Servlet API、Spring 等)將不會被打包進(jìn) JAR 文件中,減小了 SDK 的體積。


3. 結(jié)合 spring-boot-maven-pluginprovided 作用域避免 fat JAR

目標(biāo):如果你正在使用 Spring Boot,可以通過配置 Spring Boot Maven 插件,避免不必要的依賴被打包進(jìn)最終的 JAR 文件中。

步驟

  • pom.xml 中配置 spring-boot-maven-plugin,并設(shè)置 includeDependenciesfalse,確保所有依賴不會被打包進(jìn) JAR 文件中。

示例配置

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>2.5.0</version>
            <configuration>
                <!-- 不包括 SDK 和 API 依賴 -->
                <includeDependencies>false</includeDependencies>
            </configuration>
        </plugin>
    </plugins>
</build>

解釋:

  • spring-boot-maven-plugin 配置:通過設(shè)置 includeDependencies=false,Spring Boot 插件會跳過將 SDK 和 API 的依賴打包進(jìn)最終的 JAR 文件中,只將應(yīng)用的代碼打包。

  • 減小 fat JAR:最終的 JAR 文件只包含應(yīng)用代碼,而不包含 SDK 和 API 中的外部依賴,從而避免生成 fat JAR。


總結(jié)

針對你的 SDK 和 API 模塊的 fat JAR 問題,以下是優(yōu)化的主要步驟:

  1. 模塊化項(xiàng)目結(jié)構(gòu):將 SDK 和 API 拆分為獨(dú)立模塊,避免將所有代碼和依賴打包進(jìn)同一個(gè) JAR 文件中。
  2. 使用 provided 作用域:對于由容器提供的依賴(如 Servlet API、Spring 等),在 SDK 模塊中使用 provided 作用域,確保它們不會被打包進(jìn) JAR 文件中。
  3. Spring Boot 插件配置:通過 spring-boot-maven-plugin 配置 includeDependencies=false,避免將所有依賴打包進(jìn) JAR 文件中,最終減小 JAR 文件體積。

通過這些優(yōu)化,你將能夠有效避免 fat JAR 問題,減小 SDK 和 API 的體積,并且保持模塊的清晰和可維護(hù)性。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容