别再让你的SpringBoot包"虚胖"了!这份瘦身攻略请收好
作者:互联网
2026-03-22
大家好,我是小悟。
一、什么是缩小打包体积
缩小打包体积是指通过各种优化手段,减少Spring Boot应用最终部署包(通常是JAR文件)的大小。这在微服务架构和云原生部署场景中尤为重要,主要体现在以下几个方面:
1.1 核心概念
- 原始问题:Spring Boot默认采用"胖JAR"打包方式,将所有依赖(Spring框架、业务代码、嵌入式服务器、第三方库)全部打成一个可执行JAR,体积通常在50MB-200MB之间
- 优化目标:通过分离依赖、精简内容、分层构建等方式,将部署包体积缩小30%-80%
1.2 为什么重要
- 部署效率:更小的包意味着更快的上传、下载和部署速度
- 存储成本:减少镜像仓库和服务器存储空间占用
- 启动速度:精简后的包加载类文件更快,减少启动时间
- CI/CD效率:缩短构建和发布流水线时间
- 网络传输:特别是在带宽有限的环境下,小体积包优势明显
- 容器化部署:更小的镜像体积意味着更快的拉取和扩展速度
二、缩小打包体积的详细步骤
2.1 依赖优化
步骤1:分析和精简依赖
<project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-dependency-pluginartifactId>
<version>3.5.0version>
<executions>
<execution>
<id>analyzeid>
<goals>
<goal>analyzegoal>
goals>
execution>
executions>
plugin>
plugins>
build>
project>
步骤2:排除不必要的依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-tomcatartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-undertowartifactId>
dependency>
2.2 使用Spring Boot分层JAR
步骤3:配置分层JAR
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<layers>
<enabled>trueenabled>
<configuration>${project.basedir}/layers.xmlconfiguration>
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
d">
<application>
<into layer="spring-boot-loader">
<include>org/springframework/boot/loader/**include>
into>
<into layer="application" />
application>
<dependencies>
<into layer="snapshot-dependencies">
<include>*:*:*SNAPSHOTinclude>
into>
<into layer="internal-dependencies">
<include>com.yourcompany:*include>
into>
<into layer="dependencies" />
dependencies>
<layerOrder>
<layer>dependencieslayer>
<layer>spring-boot-loaderlayer>
<layer>snapshot-dependencieslayer>
<layer>internal-dependencieslayer>
<layer>applicationlayer>
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:优化静态资源和配置文件
<build>
<resources>
<resource>
<directory>src/main/resourcesdirectory>
<filtering>truefiltering>
<excludes>
<exclude>**/*.psdexclude>
<exclude>**/*.aiexclude>
<exclude>**/*.xcfexclude>
excludes>
resource>
resources>
<plugins>
<plugin>
<groupId>com.github.eirslettgroupId>
<artifactId>frontend-maven-pluginartifactId>
<version>1.12.1version>
<executions>
<execution>
<id>compress-resourcesid>
<goals>
<goal>yarngoal>
goals>
<configuration>
<arguments>buildarguments>
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原生编译
<plugin>
<groupId>org.graalvm.buildtoolsgroupId>
<artifactId>native-maven-pluginartifactId>
<version>0.9.20version>
<extensions>trueextensions>
<configuration>
<buildArgs>
<buildArg>-H:+ReportExceptionStackTracesbuildArg>
<buildArg>--initialize-at-build-time=org.springframework.util.unit.DataSizebuildArg>
<buildArg>--initialize-at-build-time=org.slf4jbuildArg>
buildArgs>
configuration>
<executions>
<execution>
<id>build-nativeid>
<goals>
<goal>compile-no-forkgoal>
goals>
<phase>packagephase>
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
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot.experimentalgroupId>
<artifactId>spring-boot-thin-maven-pluginartifactId>
<version>1.0.29.RELEASEversion>
<executions>
<execution>
<id>resolveid>
<goals>
<goal>resolvegoal>
goals>
<inherited>falseinherited>
execution>
executions>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-jar-pluginartifactId>
<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优化配置
"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
d">
<modelVersion>4.0.0modelVersion>
<groupId>com.examplegroupId>
<artifactId>slim-appartifactId>
<version>1.0.0version>
<packaging>jarpackaging>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.7.0version>
parent>
<properties>
<java.version>11java.version>
<spring-boot.thin.jar>truespring-boot.thin.jar>
<spring-boot.devtools.exclude>truespring-boot.devtools.exclude>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-tomcatartifactId>
exclusion>
<exclusion>
<groupId>org.hibernate.validatorgroupId>
<artifactId>hibernate-validatorartifactId>
exclusion>
<exclusion>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jettyartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
<scope>providedscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<layers>
<enabled>trueenabled>
layers>
<excludeDevtools>trueexcludeDevtools>
<excludes>
<exclude>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
exclude>
excludes>
configuration>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-dependency-pluginartifactId>
<version>3.5.0version>
<executions>
<execution>
<id>analyze-dependenciesid>
<goals>
<goal>analyze-onlygoal>
goals>
<configuration>
<failOnWarning>falsefailOnWarning>
configuration>
execution>
executions>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-resources-pluginartifactId>
<version>3.3.1version>
<configuration>
<encoding>UTF-8encoding>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>pdfnonFilteredFileExtension>
<nonFilteredFileExtension>pngnonFilteredFileExtension>
<nonFilteredFileExtension>jpgnonFilteredFileExtension>
nonFilteredFileExtensions>
configuration>
plugin>
plugins>
build>
project>
三、详细总结
3.1 优化效果对比
| 优化策略 | 原始体积 | 优化后体积 | 缩减比例 | 适用场景 |
|---|---|---|---|---|
| 基础依赖精简 | 80MB | 60MB | 25% | 所有项目 |
| 分层JAR + 多阶段构建 | 80MB | 45MB | 44% | 容器部署 |
| Thin Launcher | 80MB | 15MB | 81% | 微服务 |
| GraalVM Native | 80MB | 25MB | 69% | 高性能场景 |
| 综合优化 | 80MB | 18MB | 78% | 云原生部署 |
3.2 最佳实践总结
优先级策略:
- 第一优先级(立即实施)
- 使用
spring-boot-maven-plugin的分层JAR功能 - 排除不必要的传递依赖
- 使用多阶段Docker构建
- 使用
- 第二优先级(推荐实施)
- 替换为轻量级嵌入式服务器(Undertow/Jetty)
- 配置资源过滤和排除
- 使用
maven-dependency-plugin分析并移除无用依赖
- 第三优先级(可选实施)
- 采用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打包体积是一个持续优化的过程,建议:
- 从简单开始:先实施基础依赖优化和分层JAR
- 测量驱动:每次优化前后都要测量体积变化
- 平衡取舍:在体积、性能、开发效率之间找到平衡点
- 自动化集成:将体积检查集成到CI/CD流程中
- 文档记录:记录优化决策和效果,便于团队协作
通过系统性地实施上述优化策略,大多数Spring Boot应用可以将部署体积缩减50%以上,显著提升部署效率和运行时性能。
谢谢你看我的文章,既然看到这里了,如果觉得不错,随手点个赞、转发、在看三连吧,感谢感谢。那我们,下次再见。
您的一键三连,是我更新的最大动力,谢谢
山水有相逢,来日皆可期,谢谢阅读,我们再会
我手中的金箍棒,上能通天,下能探海
相关推荐
专题
+ 收藏
+ 收藏
+ 收藏
+ 收藏
+ 收藏
最新数据
相关文章
拒绝硬编码!利用 Java SPI 打造一个可插拔的代码解析器
给 Spring Boot 接口加了幂等保护:Token 机制 + 结果缓存,一个注解搞定
一站式了解接口防刷(限流)的基本操作
ThreadForge v1.1.0 发布:让 Java 并发更接近 Go 的开发体验
各版本JDK对比:JDK 21 特性详解
JVM 内存溢出排查
LangChain4j Prompt 提示词工程
彻底重绘Spring Boot性能版图,资源占用缩减80%
百度智能云模型接入
CompletableFuture深度解析:异步编程与任务编排的实现
AI精选
