一、什么是缩小打包体积
缩小打包体积是指通过各种优化手段,减少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 优化效果对比
| 优化策略 | 原始体积 | 优化后体积 | 缩减比例 | 适用场景 |
|---|---|---|---|---|
| 基础依赖精简 | 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%以上,显著提升部署效率和运行时性能。
以上就是springboot缩小打包体积的详细步骤的详细内容,更多关于springboot缩小打包体积的资料请关注代码网其它相关文章!
发表评论