You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot Maven项目如何分离应用Jar与依赖并生成可执行Jar

解决方案步骤

1. 配置Maven生成不含依赖的可执行Jar

不要直接移除spring-boot-maven-plugin,而是调整插件配置,让它只打包应用代码,同时用maven-dependency-plugin把依赖单独导出(后续上传到远程位置)。

修改pom.xml的插件配置:

<!-- 导出所有依赖到单独目录 -->
<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>
                <!-- 依赖导出到target/dependencies目录 -->
                <outputDirectory>${project.build.directory}/dependencies</outputDirectory>
                <overWriteReleases>false</overWriteReleases>
                <overWriteSnapshots>false</overWriteSnapshots>
                <overWriteIfNewer>true</overWriteIfNewer>
            </configuration>
        </execution>
    </executions>
</plugin>

<!-- 生成可执行的轻量应用Jar,不包含依赖 -->
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <!-- 仅打包当前项目代码,排除所有第三方依赖 -->
        <includes>
            <include>
                <groupId>${project.groupId}</groupId>
                <artifactId>${project.artifactId}</artifactId>
            </include>
        </includes>
        <!-- 指定你的Spring Boot主类,确保Manifest包含Main-Class属性 -->
        <mainClass>com.yourpackage.YourApplicationMainClass</mainClass>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>

执行mvn clean package后,会得到两个产物:

  • target/abc.jar:仅含应用代码的可执行Jar(体积约3MB)
  • target/dependencies/:所有第三方依赖Jar,将这个目录下的文件上传到你的远程存储(如静态文件服务器、对象存储),得到远程根路径(例如http://your-remote-server/dependencies/)

2. 运行应用时加载远程依赖

方法一:直接通过URL类路径启动

假设远程依赖的根URL是http://your-remote-server/dependencies/,启动时将远程依赖的URL加入类路径:

# Linux/macOS系统用冒号分隔类路径
java -cp "target/abc.jar:http://your-remote-server/dependencies/*.jar" com.yourpackage.YourApplicationMainClass

# Windows系统用分号分隔类路径
java -cp "target/abc.jar;http://your-remote-server/dependencies/*.jar" com.yourpackage.YourApplicationMainClass

如果依赖数量较多,手动写URL麻烦,可以先生成包含所有远程依赖URL的文本文件(比如deps-urls.txt),再通过@引用:

# 示例:生成依赖URL列表文件
echo "http://your-remote-server/dependencies/spring-boot-starter-web-3.2.0.jar" >> deps-urls.txt
echo "http://your-remote-server/dependencies/spring-boot-autoconfigure-3.2.0.jar" >> deps-urls.txt
# 补充其他依赖...

# 启动应用
java -cp "target/abc.jar:@deps-urls.txt" com.yourpackage.YourApplicationMainClass

方法二:自定义类加载器(适合生产环境)

如果需要缓存远程依赖、动态更新版本等灵活逻辑,可以实现自定义类加载器,在应用启动前将远程依赖下载到本地临时目录,再加载:

public class YourApplicationMainClass {
    public static void main(String[] args) throws Exception {
        // 远程依赖根地址
        String remoteDepRoot = "http://your-remote-server/dependencies/";
        // 本地缓存目录
        File cacheDir = new File(System.getProperty("java.io.tmpdir"), "app-deps");
        cacheDir.mkdirs();

        // 从配置文件或固定列表读取依赖Jar名称(需和编译版本一致)
        List<String> depJars = Arrays.asList(
            "spring-boot-starter-web-3.2.0.jar",
            "spring-boot-autoconfigure-3.2.0.jar"
            // 其他依赖...
        );

        for (String jar : depJars) {
            URL remoteUrl = new URL(remoteDepRoot + jar);
            File localJar = new File(cacheDir, jar);
            // 本地无缓存时,下载远程Jar
            if (!localJar.exists()) {
                try (InputStream in = remoteUrl.openStream();
                     FileOutputStream out = new FileOutputStream(localJar)) {
                    byte[] buffer = new byte[1024];
                    int len;
                    while ((len = in.read(buffer)) != -1) {
                        out.write(buffer, 0, len);
                    }
                }
            }
            // 将本地缓存Jar加入类加载路径
            URLClassLoader classLoader = new URLClassLoader(
                new URL[]{localJar.toURI().toURL()},
                Thread.currentThread().getContextClassLoader()
            );
            Thread.currentThread().setContextClassLoader(classLoader);
        }

        // 启动Spring Boot应用
        SpringApplication.run(YourApplicationMainClass.class, args);
    }
}

3. 关键注意事项

  • 确保远程服务器的依赖文件可被应用访问(无权限限制、网络通畅)
  • 远程依赖的版本必须和应用编译时的版本完全一致,避免兼容性问题
  • 生产环境建议给远程依赖配置CDN或本地缓存,减少启动延迟

内容的提问来源于stack exchange,提问作者Mahesh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 07:27:48