前言
在使用 Spring Boot 开发项目时,我们通常会使用 Maven 作为构建工具。Maven 负责依赖管理、编译、打包等任务。但在实际开发中,经常遇到一个问题:Spring Boot 项目在本地运行正常,但使用 mvn package
打包成 JAR 后却无法运行或启动失败。
本文将从多个角度分析常见错误场景,并提供详细的排查和解决方案,帮助你彻底解决 Spring Boot Maven 打包后运行失败的问题。
一、问题背景
Spring Boot 应用默认使用 spring-boot-maven-plugin
插件进行打包,生成一个包含所有依赖的可执行 JAR 文件(俗称“fat jar”)。然而,在某些情况下,构建后的 JAR 文件可能缺少主类、依赖未正确打包、配置文件缺失等问题,导致运行时报错。
二、常见错误类型及解决方案
1. 缺少主类信息(no main manifest attribute)
现象
no main manifest attribute, in your-app.jar
原因
JAR 包中的 MANIFEST.MF
文件没有指定主类(Main-Class),Java 无法识别程序入口点。
解决方案
确保在 pom.xml
中正确配置了 spring-boot-maven-plugin
插件,并显式指定主类:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.example.demo.DemoApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
或者,如果你使用的是 Spring Boot 的 parent POM,则可以直接启用插件而无需额外配置:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
验证方法
查看 JAR 包中的 MANIFEST 是否包含主类信息:
unzip -p your-app.jar META-INF/MANIFEST.MF
2. 类找不到(ClassNotFoundException / NoClassDefFoundError)
现象
java.lang.ClassNotFoundException: com.example.service.SomeService
原因
- 依赖未被正确打包进最终的 JAR 文件
- 某些依赖的作用域设置为
provided
或test
- 没有使用
spring-boot-maven-plugin
插件
解决方案
确保依赖作用域正确:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!-- 不要使用 provided --> </dependency>
使用
spring-boot-maven-plugin
进行 repackage:<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin>
查看 JAR 包中是否包含目标类:
jar tf your-app.jar | grep SomeService.class
3. 配置文件未被打包或路径不对
现象
应用启动时报错:
Could not load property source from location 'classpath:/application.properties'
原因
- 配置文件未放在标准目录
src/main/resources
下 - Maven 打包时未启用资源过滤(filtering)
解决方案
- 将配置文件放在
src/main/resources
目录下 - 如果需要替换占位符(如
${my.property}
),请启用资源过滤:
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
- 查看 JAR 包中是否包含配置文件:
jar tf your-app.jar | grep application.properties
4. 多模块项目打包问题
现象
子模块依赖未正确打包,导致类找不到或主程序找不到。
原因
- 子模块未安装到本地仓库
- 主模块未正确声明依赖关系
解决方案
在父项目的
pom.xml
中定义模块顺序:<modules> <module>common</module> <module>web</module> </modules>
在主模块中添加对子模块的依赖:
<dependency> <groupId>com.example</groupId> <artifactId>common</artifactId> <version>1.0.0</version> </dependency>
构建前先执行:
mvn clean install
主模块中使用
spring-boot-maven-plugin
插件重新打包:<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin>
5. JDK 版本不一致导致的错误
现象
java.lang.UnsupportedClassVersionError: major.minor version 61.0
原因
编译环境与运行环境使用的 Java 版本不一致。
解决方案
统一编译与运行环境的 JDK 版本,在 pom.xml
中指定编译版本:
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
6. 打包命令使用错误
现象
构建的 JAR 文件缺失内容或不可执行
正确做法
使用以下命令进行打包:
mvn clean package
确保 target/your-app.jar
是一个完整的、可执行的 Spring Boot 应用。
三、推荐的排查步骤
步骤 | 操作 | 说明 |
---|---|---|
1 | 查看日志 | 定位具体错误堆栈 |
2 | 检查 JAR 内容 | jar tf your-app.jar |
3 | 检查主类信息 | unzip -p your-app.jar META-INF/MANIFEST.MF |
4 | 验证依赖完整性 | 查看 BOOT-INF/lib/ 目录是否存在 |
5 | 本地测试运行 | java -jar your-app.jar |
四、完整示例:pom.xml 配置模板
<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>demo</artifactId>
<version>1.0.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.1</version>
<relativePath/>
</parent>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.example.demo.DemoApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
五、总结
问题类型 | 常见表现 | 解决方案 |
---|---|---|
缺少主类 | no main manifest attribute | 配置 <mainClass> |
类找不到 | ClassNotFoundException | 检查依赖 + repackage |
配置文件缺失 | 找不到 application.properties | 放入 resources + filtering |
多模块问题 | 类找不到 | 先 install 子模块 |
JDK 版本不一致 | UnsupportedClassVersionError | 统一 source/target JDK |
插件配置错误 | 构建失败或不可执行 | 正确使用 spring-boot-maven-plugin |
六、结语
Spring Boot + Maven 是现代 Java Web 开发的标准组合,但打包过程中的细节容易出错。通过理解构建流程、掌握关键插件的使用以及学会如何检查 JAR 包内容,你可以快速定位并修复大多数打包运行失败的问题。