如何解决项目中的fat jar

方案:通过拆分模块和使用 provided 作用域优化 SDK 和 API 的依赖

背景:

你们项目的 fat JAR 问题主要集中在 API 和 SDK 包里。通过将 SDK 和 API 进行模块化,并且合理使用 Maven 的 provided 作用域,可以避免不必要的依赖被打包到最终的 JAR 文件中,从而解决 fat JAR 问题。

1. 模块化项目结构:将 SDK 和 API 拆分为独立模块

目标:通过模块化管理 SDK 和 API,确保每个模块只包含必要的代码和依赖,不将所有依赖都打包在同一个 JAR 文件中。

步骤

  • 拆分 SDK 和 API 为独立模块:你可以将 SDK 和 API 分别拆分为独立的 Maven 模块,分别负责自己的功能。这样,SDK 模块可以单独发布,而 API 模块仅用于定义接口和通用服务,不包含实现代码。

  • API 模块:只包含 API 的定义(接口、DTO 等),不包含实现。这个模块将作为 SDK 模块的依赖。

  • SDK 模块:包含 SDK 的实现,依赖于 API 模块。

目录结构示例

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 拆分为独立模块,SDK 模块只依赖 API 模块,避免了所有依赖都被打包在同一个 JAR 文件中的问题。
  • 减少不必要的依赖:只将 SDK 和 API 需要的依赖包含在 SDK 模块中,并将这些依赖的 scope 设置为 provided,避免它们被打包进 SDK JAR 中。

2. 使用 provided 作用域来优化 SDK 和 API 依赖

目标:确保在编译和测试时需要的依赖,在打包时不会被包含在最终的 JAR 文件中。

步骤

  • 标记容器提供的依赖:对于那些由外部容器或环境提供的依赖(例如 Servlet API、JSP、Spring),使用 provided 作用域来标记它们。

  • SDK 中使用 provided 作用域:如果你的 SDK 依赖于一些框架(如 Spring 或 Servlet API),并且这些框架在运行时已经由外部容器提供,那么这些依赖应设置为 provided,这样就不会被打包进 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 由应用服务器提供 -->
</dependency>

解释:

  • provided 作用域:表示这些依赖只在编译时可用,运行时由外部容器提供。这样,它们不会被打包进 SDK 模块的 JAR 文件中。

  • 减少 fat JAR 大小:通过使用 provided 作用域,容器提供的依赖(如 Servlet API、Spring 等)将不会被打包进 JAR 文件中,减小了 SDK 的体积。


3. 结合 spring-boot-maven-pluginprovided 作用域避免 fat JAR

目标:如果你正在使用 Spring Boot,可以通过配置 Spring Boot Maven 插件,避免不必要的依赖被打包进最终的 JAR 文件中。

步骤

  • pom.xml 中配置 spring-boot-maven-plugin,并设置 includeDependenciesfalse,确保所有依赖不会被打包进 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 配置:通过设置 includeDependencies=false,Spring Boot 插件会跳过将 SDK 和 API 的依赖打包进最终的 JAR 文件中,只将应用的代码打包。

  • 减小 fat JAR:最终的 JAR 文件只包含应用代码,而不包含 SDK 和 API 中的外部依赖,从而避免生成 fat JAR。


总结

针对你的 SDK 和 API 模块的 fat JAR 问题,以下是优化的主要步骤:

  1. 模块化项目结构:将 SDK 和 API 拆分为独立模块,避免将所有代码和依赖打包进同一个 JAR 文件中。
  2. 使用 provided 作用域:对于由容器提供的依赖(如 Servlet API、Spring 等),在 SDK 模块中使用 provided 作用域,确保它们不会被打包进 JAR 文件中。
  3. Spring Boot 插件配置:通过 spring-boot-maven-plugin 配置 includeDependencies=false,避免将所有依赖打包进 JAR 文件中,最终减小 JAR 文件体积。

通过这些优化,你将能够有效避免 fat JAR 问题,减小 SDK 和 API 的体积,并且保持模块的清晰和可维护性。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容