Skip to content

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 等参数可能不生效!

关键说明:

  1. -Dloader.path Spring Boot 通过此参数加载外部依赖目录。
  2. 路径格式
    需使用相对路径(./libs)或绝对路径(/opt/app/libs),确保 libs 与主 JAR 同级。
  3. 依赖范围
    配置中的 <includeScope>runtime</includeScope> 确保运行时所需依赖均被复制。
  4. 系统属性(以 -D 开头的参数) 可以放在命令行的任何位置,但通常建议放在 -jar 或 -cp 之前,或者放在主类名之前。
  5. -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