当前位置: 首页 > news >正文

别再让你的SpringBoot包虚胖了!这份瘦身攻略请收好

大家好,我是小悟。

一、什么是缩小打包体积

缩小打包体积是指通过各种优化手段,减少Spring Boot应用最终部署包(通常是JAR文件)的大小。这在微服务架构和云原生部署场景中尤为重要,主要体现在以下几个方面:

1.1 核心概念

  • 原始问题:Spring Boot默认采用"胖JAR"打包方式,将所有依赖(Spring框架、业务代码、嵌入式服务器、第三方库)全部打成一个可执行JAR,体积通常在50MB-200MB之间
  • 优化目标:通过分离依赖、精简内容、分层构建等方式,将部署包体积缩小30%-80%

1.2 为什么重要

  • 部署效率:更小的包意味着更快的上传、下载和部署速度
  • 存储成本:减少镜像仓库和服务器存储空间占用
  • 启动速度:精简后的包加载类文件更快,减少启动时间
  • CI/CD效率:缩短构建和发布流水线时间
  • 网络传输:特别是在带宽有限的环境下,小体积包优势明显
  • 容器化部署:更小的镜像体积意味着更快的拉取和扩展速度

二、缩小打包体积的详细步骤

2.1 依赖优化

步骤1:分析和精简依赖

<!-- pom.xml --> <project> <!-- 使用Maven依赖分析插件 --> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>3.5.0</version> <executions> <execution> <id>analyze</id> <goals> <goal>analyze</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>

步骤2:排除不必要的依赖

<!-- 排除Tomcat(如果使用Jetty或Undertow) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <!-- 添加轻量级的Undertow替代 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency>
2.2 使用Spring Boot分层JAR

步骤3:配置分层JAR

<!-- pom.xml - 使用Spring Boot 2.3+的分层特性 --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <layers> <enabled>true</enabled> <configuration>${project.basedir}/layers.xml</configuration> </layers> </configuration> </plugin> </plugins> </build>

创建自定义分层配置layers.xml

<layers xmlns="http://www.springframework.org/schema/boot/layers" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/boot/layers https://www.springframework.org/schema/boot/layers/layers-2.3.xsd"> <application> <into layer="spring-boot-loader"> <include>org/springframework/boot/loader/**</include> </into> <into layer="application" /> </application> <dependencies> <into layer="snapshot-dependencies"> <include>*:*:*SNAPSHOT</include> </into> <into layer="internal-dependencies"> <include>com.yourcompany:*</include> </into> <into layer="dependencies" /> </dependencies> <layerOrder> <layer>dependencies</layer> <layer>spring-boot-loader</layer> <layer>snapshot-dependencies</layer> <layer>internal-dependencies</layer> <layer>application</layer> </layerOrder> </layers>
2.3 构建Docker镜像优化

步骤4:创建优化的Dockerfile

# 使用多阶段构建 # 构建阶段 FROM maven:3.8.4-openjdk-11-slim AS builder WORKDIR /app COPY pom.xml . # 下载依赖(利用Docker缓存) RUN mvn dependency:go-offline COPY src ./src # 打包应用 RUN mvn clean package -DskipTests # 运行阶段 FROM openjdk:11-jre-slim WORKDIR /app # 创建非root用户 RUN addgroup --system --gid 1001 appuser && \ adduser --system --uid 1001 --gid 1001 appuser # 从构建阶段复制JAR COPY --from=builder --chown=appuser:appuser /app/target/*.jar app.jar # 提取分层JAR RUN java -Djarmode=layertools -jar app.jar extract # 复制分层内容 COPY --from=builder --chown=appuser:appuser /app/dependencies/ ./ COPY --from=builder --chown=appuser:appuser /app/spring-boot-loader/ ./ COPY --from=builder --chown=appuser:appuser /app/snapshot-dependencies/ ./ COPY --from=builder --chown=appuser:appuser /app/application/ ./ USER appuser # 优化JVM参数 ENTRYPOINT ["java", "-XX:+UseContainerSupport", "-XX:MaxRAMPercentage=75.0", "-XX:+UseG1GC", "-XX:+OptimizeStringConcat", "-XX:+UseStringDeduplication", "org.springframework.boot.loader.JarLauncher"]
2.4 资源文件优化

步骤5:优化静态资源和配置文件

<!-- 在pom.xml中配置资源过滤和压缩 --> <build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> <excludes> <exclude>**/*.psd</exclude> <exclude>**/*.ai</exclude> <exclude>**/*.xcf</exclude> </excludes> </resource> </resources> <plugins> <!-- 压缩CSS/JS --> <plugin> <groupId>com.github.eirslett</groupId> <artifactId>frontend-maven-plugin</artifactId> <version>1.12.1</version> <executions> <execution> <id>compress-resources</id> <goals> <goal>yarn</goal> </goals> <configuration> <arguments>build</arguments> </configuration> </execution> </executions> </plugin> </plugins> </build>
2.5 自定义ClassLoader和数据压缩

步骤6:实现自定义类加载器

// 自定义类加载器实现懒加载 public class LazyLoadingClassLoader extends ClassLoader { private Map<String, byte[]> classBytesMap = new ConcurrentHashMap<>(); public void registerClassBytes(String className, byte[] bytes) { classBytesMap.put(className, bytes); } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { byte[] bytes = classBytesMap.remove(name); if (bytes == null) { return super.findClass(name); } return defineClass(name, bytes, 0, bytes.length); } }

步骤7:配置文件压缩

@Configuration @PropertySource(value = "classpath:application.properties", encoding = "UTF-8") public class CompressedConfig { @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); // 启用压缩属性文件 configurer.setIgnoreUnresolvablePlaceholders(true); configurer.setFileEncoding("UTF-8"); return configurer; } }
2.6 使用GraalVM Native Image

步骤8:配置GraalVM原生编译

<!-- 添加native-image插件 --> <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> <version>0.9.20</version> <extensions>true</extensions> <configuration> <buildArgs> <buildArg>-H:+ReportExceptionStackTraces</buildArg> <buildArg>--initialize-at-build-time=org.springframework.util.unit.DataSize</buildArg> <buildArg>--initialize-at-build-time=org.slf4j</buildArg> </buildArgs> </configuration> <executions> <execution> <id>build-native</id> <goals> <goal>compile-no-fork</goal> </goals> <phase>package</phase> </execution> </executions> </plugin>
2.7 自动化瘦身脚本

步骤9:创建自动化瘦身脚本

#!/bin/bash # slim-down.sh - 自动化瘦身脚本 echo "开始Spring Boot应用瘦身..." # 1. 分析当前JAR大小 JAR_FILE=$(ls target/*.jar | head -1) ORIGINAL_SIZE=$(du -h $JAR_FILE | cut -f1) echo "原始JAR大小: $ORIGINAL_SIZE" # 2. 提取并分析依赖 mkdir -p tmp/unpacked cd tmp/unpacked jar -xf ../../$JAR_FILE cd BOOT-INF/lib # 3. 找出大文件依赖 echo "前10大依赖:" ls -lhS | head -10 # 4. 分析可移除的依赖 cd ../../.. rm -rf tmp # 5. 重新打包(使用分层JAR) echo "执行分层JAR打包..." mvn clean package -Dspring-boot.thin.jar=true # 6. 构建优化后的Docker镜像 echo "构建优化镜像..." docker build -t optimized-app:latest -f Dockerfile.multistage . NEW_JAR=$(ls target/*.jar | head -1) NEW_SIZE=$(du -h $NEW_JAR | cut -f1) REDUCTION=$(echo "scale=2; ($(du -b $JAR_FILE | cut -f1) - $(du -b $NEW_JAR | cut -f1)) / $(du -b $JAR_FILE | cut -f1) * 100" | bc) echo "优化完成!" echo "原始大小: $ORIGINAL_SIZE" echo "优化后大小: $NEW_SIZE" echo "体积减少: $REDUCTION%"
2.8 使用Thin Launcher

步骤10:配置Thin Launcher

<!-- 使用Spring Boot Thin Launcher --> <build> <plugins> <plugin> <groupId>org.springframework.boot.experimental</groupId> <artifactId>spring-boot-thin-maven-plugin</artifactId> <version>1.0.29.RELEASE</version> <executions> <execution> <id>resolve</id> <goals> <goal>resolve</goal> </goals> <inherited>false</inherited> </execution> </executions> </plugin> <!-- 修改默认打包插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifest> <mainClass>${start-class}</mainClass> </manifest> <manifestEntries> <Spring-Boot-Version>${spring-boot.version}</Spring-Boot-Version> <Spring-Boot-Lib>lib/</Spring-Boot-Lib> </manifestEntries> </archive> </configuration> </plugin> </plugins> </build>
2.9 配置排除和瘦身优化

步骤11:完整的pom.xml优化配置

<?xml version="1.0" encoding="UTF-8"?> <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>slim-app</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.0</version> </parent> <properties> <java.version>11</java.version> <!-- 启用瘦身模式 --> <spring-boot.thin.jar>true</spring-boot.thin.jar> <!-- 排除devtools --> <spring-boot.devtools.exclude>true</spring-boot.devtools.exclude> </properties> <dependencies> <!-- 核心依赖,排除不必要的传递依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> <exclusion> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </exclusion> </exclusions> </dependency> <!-- 使用轻量级服务器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> <!-- 条件化引入依赖 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <!-- 启用分层JAR --> <layers> <enabled>true</enabled> </layers> <!-- 排除devtools --> <excludeDevtools>true</excludeDevtools> <!-- 配置需要排除的依赖 --> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> <!-- 依赖分析插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>3.5.0</version> <executions> <execution> <id>analyze-dependencies</id> <goals> <goal>analyze-only</goal> </goals> <configuration> <failOnWarning>false</failOnWarning> </configuration> </execution> </executions> </plugin> <!-- 资源优化插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.3.1</version> <configuration> <encoding>UTF-8</encoding> <nonFilteredFileExtensions> <nonFilteredFileExtension>pdf</nonFilteredFileExtension> <nonFilteredFileExtension>png</nonFilteredFileExtension> <nonFilteredFileExtension>jpg</nonFilteredFileExtension> </nonFilteredFileExtensions> </configuration> </plugin> </plugins> </build> </project>

三、详细总结

3.1 优化效果对比
优化策略原始体积优化后体积缩减比例适用场景
基础依赖精简80MB60MB25%所有项目
分层JAR + 多阶段构建80MB45MB44%容器部署
Thin Launcher80MB15MB81%微服务
GraalVM Native80MB25MB69%高性能场景
综合优化80MB18MB78%云原生部署
3.2 最佳实践总结

优先级策略:

  1. 第一优先级(立即实施)
    • 使用spring-boot-maven-plugin的分层JAR功能
    • 排除不必要的传递依赖
    • 使用多阶段Docker构建
  2. 第二优先级(推荐实施)
    • 替换为轻量级嵌入式服务器(Undertow/Jetty)
    • 配置资源过滤和排除
    • 使用maven-dependency-plugin分析并移除无用依赖
  3. 第三优先级(可选实施)
    • 采用Thin Launcher方案
    • 使用GraalVM Native Image
    • 实现自定义类加载器
3.3 关键注意事项

1. 兼容性考量

  • Native Image对反射、动态代理支持有限
  • Thin Launcher可能需要调整类加载逻辑
  • 分层JAR需要Spring Boot 2.3+

2. 性能权衡

  • Native Image启动快但构建慢
  • Thin Launcher首次启动需要下载依赖
  • 过度精简可能影响功能完整性

3. 监控与维护

  • 建立体积监控基准
  • 在CI/CD流程中自动检查JAR大小
  • 定期review依赖使用情况
3.4 实施建议路线图

3.5 最后

缩小Spring Boot打包体积是一个持续优化的过程,建议:

  1. 从简单开始:先实施基础依赖优化和分层JAR
  2. 测量驱动:每次优化前后都要测量体积变化
  3. 平衡取舍:在体积、性能、开发效率之间找到平衡点
  4. 自动化集成:将体积检查集成到CI/CD流程中
  5. 文档记录:记录优化决策和效果,便于团队协作

通过系统性地实施上述优化策略,大多数Spring Boot应用可以将部署体积缩减50%以上,显著提升部署效率和运行时性能。

谢谢你看我的文章,既然看到这里了,如果觉得不错,随手点个赞、转发、在看三连吧,感谢感谢。那我们,下次再见。

您的一键三连,是我更新的最大动力,谢谢

山水有相逢,来日皆可期,谢谢阅读,我们再会

我手中的金箍棒,上能通天,下能探海

http://www.jsqmd.com/news/509636/

相关文章:

  • Qwen3.5-9B开源大模型部署案例:中小企业低成本GPU方案
  • 梯形图转C代码总出错?3大隐性语法陷阱+5步精准校验法,97%工程师忽略的转换一致性保障方案
  • 别再只盯着运放了!用跨阻放大器搞定光电传感器信号调理,实测电路分享
  • SolidWorks设计工作站如何共享给8-10个并发
  • 嵌入式多串口命令监听框架设计与实践
  • Gin框架实战:5分钟搞定一个RESTful API服务(附完整代码)
  • Photoshop-Export-Layers-to-Files-Fast:3大方案实现图层高效导出与批量处理
  • 【RS】ENVI 5.6.2 实战:六大图像融合算法全解析与场景适配指南
  • 模型微调指南:优化Qwen3-32B在OpenClaw中的任务表现
  • ANIMATEDIFF PRO效果展示:雨滴下落+玻璃反光的超写实动态场景
  • Gitee团队协作全流程:从SSH配置到仓库管理的保姆级指南
  • Qwen-Image-2512-Pixel-Art-LoRA 模型版本管理与升级实践
  • Qwen3-32B-Chat快速部署:无需conda/pip,纯镜像内环境启动零报错实录
  • Git “archive“ 命令实战指南:从基础到高阶应用
  • OpenClaw配置优化:Qwen3-32B模型参数对任务成功率的影响
  • LiuJuan20260223Zimage赋能微信小程序:智能对话功能快速实现
  • MusePublic艺术创作引擎企业级集成方案:SpringBoot篇
  • BBDown:命令行B站视频下载器终极指南
  • C++ 08:对象数组——批量管理对象的高效方式
  • 开源字体Outfit:现代几何无衬线设计的多场景解决方案
  • RTOS移植不求人:从芯片手册读取时钟树、NVIC配置、SysTick重定向到任务调度器初始化,一文打通全部底层链路
  • 第 4 篇:内容即数据——frontmatter 规范、数据结构与构建链路的工程化设计
  • Qwen3-32B-Chat私有部署一文详解:RTX4090D显存优化、低内存加载与量化支持
  • JPEGView:高效轻量级图像查看器的技术解析与应用指南
  • 开源力量:跟随社区百万下载量模型all-MiniLM-L6-v2,快速入门句子嵌入技术
  • 如何在3分钟内用AI生成专业演示文稿:PPTAgent智能演示文稿生成工具完整指南
  • DAMO-YOLO与MySQL数据库集成:检测结果存储与分析方案
  • Botty完全指南:暗黑破坏神2自动化刷宝的智能识别技术与实战优化策略
  • Vue2项目实战:用AntV G6打造可折叠树形结构(附完整代码)
  • Pixel Dimension Fissioner开发者指南:MT5-Zero-Shot-Augment调用全解析