Spring Boot 将依赖包单独打包到 lib 目录
在 Spring Boot 项目中,将依赖包单独打包到 libs
目录下可显著减小主 JAR 体积,便于增量更新。以下是具体配置步骤及启动方法:
⚙️ 一、POM 配置:分离依赖到 libs 目录
在 pom.xml
中添加以下插件配置:
xml
<build>
<plugins>
<!-- 配置 Spring Boot 打包插件(关键:排除默认依赖打包) -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- 指定启动类 -->
<mainClass>com.example.MainApplication</mainClass>
<!-- 必须!!!启用 SpringBoot 的 PropertiesLauncher -->
<layout>ZIP</layout>
<!-- 排除依赖库,仅打包项目代码 -->
<includes>
<include>
<groupId>nothing</groupId> <!-- 特殊标记,排除所有依赖 -->
</include>
</includes>
</configuration>
</plugin>
<!-- 复制依赖到 target/libs 目录 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<!-- lib 依赖包输出目录 -->
<outputDirectory>${project.build.directory}/libs</outputDirectory>
<!-- 包含运行时依赖 -->
<includeScope>runtime</includeScope>
<!-- 是否排除传递依赖(间接依赖) -->
<excludeTransitive>false</excludeTransitive>
<!-- 覆盖更新 -->
<overWriteIfNewer>true</overWriteIfNewer>
<!-- 是否去除版本号 -->
<stripVersion>false</stripVersion>
<!-- 默认为 true(只保留基础版本),需显式设为 false(保留 SNAPSHOT 的时间戳版本) -->
<useBaseVersion>false</useBaseVersion>
<!-- 是否复制 POM 文件记录精确版本(true: 会复制 pom.xml 到 outputDirectory 目录) -->
<copyPom>false</copyPom>
<overWriteReleases>false</overWriteReleases>
<!-- 允许覆盖旧快照 -->
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
📦 二、打包操作
执行 Maven 命令生成分离结构的输出:
bash
mvn clean package
# 或指定更多参数
mvn clean package -Dmaven.test.skip=true --update-snapshots -s D:\maven\settings.xml
打包后目录结构如下:
txt
target/
├── classes/ # 仅含项目代码(体积显著减小)
├── app.jar # 仅含项目代码(体积显著减小)
└── libs/ # 所有依赖的 JAR 文件
├── spring-core-xx.jar
├── mysql-connector-xx.jar
└── ...
🚀 三、启动命令:-Dloader.path
使用 -Dloader.path
参数指向 libs
目录启动应用:
bash
java -Dloader.path="./classes,./lib" -jar app.jar
# 增加 jvm 和 -D 参数
java -Xms512m -Xmx2048m -XX:MaxMetaspaceSize=256m -Dname=YourApp -Duser.timezone=Asia/Shanghai -Dloader.path="./classes,./lib" -jar app.jar
bash
# JVM_OPTS 变量
set JVM_OPTS=-Dname=%AppName% -Dfile.encoding=UTF-8 -Duser.timezone=Asia/Shanghai -Xms512m -Xmx2048m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC
java %JVM_OPTS% -Dloader.path="./classes,./lib" -jar app.jar
注意:JVM_OPTS 等号后面不要加双引号,否则 -Xmx2048m 等参数可能不生效!
关键说明:
-Dloader.path
Spring Boot 通过此参数加载外部依赖目录。- 路径格式
需使用相对路径(./libs
)或绝对路径(/opt/app/libs
),确保libs
与主 JAR 同级。 - 依赖范围
配置中的<includeScope>runtime</includeScope>
确保运行时所需依赖均被复制。 - 系统属性(以 -D 开头的参数) 可以放在命令行的任何位置,但通常建议放在 -jar 或 -cp 之前,或者放在主类名之前。
-Dloader.path="./classes,./lib"
优先加载 classes 目录下的类,再加载 lib 目录下的类。以解决 classes 目录下有覆盖 lib 目录下的 .jar 或 .class 文件。
可选
有这个时,在 java -jar 启动时可省略指定 lib 目录。
xml
<build>
<plugins>
<!-- 修正 MANIFEST.MF 中的 Class-Path -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<!-- 启用 Class-Path -->
<addClasspath>true</addClasspath>
<!-- 前缀为lib/ -->
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.example.MainApplication</mainClass>
</manifest>
<manifestEntries>
<!-- 包含当前目录 -->
<Class-Path>.</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
shell
# 无 maven-jar-plugin 插件时的启动命令:
java -Dloader.path="./classes,./lib" -jar app.jar
shell
# 有 maven-jar-plugin 插件时的启动命令:
java -jar app.jar
# 自己工程有覆盖 lib 下的 .jar 或 .class
java -Dloader.path="./classes" -jar app.jar