Spring Boot应用启动卡在JVM running阶段无法正常访问服务
问题描述
- 项目结构参考:

- 基础环境:使用MySQL数据库,已提前创建名为
employeemanager的数据库。 - 故障表现:
- 应用启动过程中长时间卡住无后续启动日志,卡住阶段截图:

- 浏览器访问
localhost:8080时无正常响应,访问异常截图:
- 应用启动过程中长时间卡住无后续启动日志,卡住阶段截图:
- 已尝试的无效操作:
- 在
EmployeeManagerApplication.java中添加@ComponentScan(basePackages={"tn.poulina.EmployeeManager.model"} )注解 - 将
EmployeeManagerApplication.java移动到model包下
两种操作后故障依旧,应用始终无法正常启动对外提供服务。
- 在
核心文件代码
EmployeeManagerApplication.java
package tn.poulina.EmployeeManager; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; /*@ComponentScan(basePackages={"tn.poulina.EmployeeManager.model"} )*/ @SpringBootApplication public class EmployeeManagerApplication { public static void main(String[] args) { SpringApplication.run(EmployeeManagerApplication.class, args); } }
Employee.java
package tn.poulina.EmployeeManager.model; import java.io.Serializable; import javax.persistence.*; @Entity public class Employee implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(nullable = false,updatable = false) private Long id; private String name; private String email; private String jobTitle; private String phone; private String imageUrl; @Column(nullable = false,updatable = false) private String employeeCode; public Employee() {} public Employee(String name,String email,String jobTitle ,String phone ,String imageUrl,String employeeCode) { this.name=name; this.email=email; this.jobTitle=jobTitle; this.phone=phone; this.imageUrl=imageUrl; this.employeeCode=employeeCode; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getJobTitle() { return jobTitle; } public void setJobTitle(String jobTitle) { this.jobTitle = jobTitle; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getImageUrl() { return imageUrl; } public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; } public String getEmployeeCode() { return employeeCode; } public void setEmployeeCode(String employeeCode) { this.employeeCode = employeeCode; } @Override public String toString(){ return "Employee{"+"id="+id+"/name="+name+"/email="+email+"/jobTitle="+jobTitle+"/phone="+phone+"/imageUrl="+imageUrl+"}"; } }
application.properties
# MySQL Configuration spring.datasource.url=jdbc:mysql://localhost:3306/employeemanager spring.datasource.username=root spring.datasource.password=root spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=update spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
问题原因与解决方案
你之前尝试的两个排查方向完全错误:Spring Boot启动类放在根包tn.poulina.EmployeeManager下时,@SpringBootApplication自带的包扫描默认会覆盖当前包及所有子包,根本不需要额外加@ComponentScan指定model包,反而加了这个配置后Spring只会扫描model包,其他层的Bean会全部加载失败;把启动类移到model包下更是会让扫描范围进一步缩小,完全解决不了问题。
启动卡住、8080无响应,按优先级排查以下问题:
- 第一优先级:排查数据库连接问题(90%以上的同类故障都是这个原因)
- 先确认本地MySQL服务是否正常启动:Windows系统打开服务面板找到MySQL服务查看运行状态,Linux系统执行
systemctl status mysqld检查,服务没启动先启动服务。 - 核对数据库连接参数:用命令行或数据库客户端直接测试连接,确认3306端口正确、root账号密码确实是你配置里的
root,连不上就把配置里的端口、账号密码改成实际可用的值。 - 补全数据库连接必要参数,把
application.properties里的datasource.url替换为:
高版本MySQL不加这几个参数,经常会卡在建立连接阶段,控制台没有明确报错看起来像“卡住”。spring.datasource.url=jdbc:mysql://localhost:3306/employeemanager?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true - 核对Hibernate方言配置:如果你本地装的是MySQL8.x版本,把方言配置从
MySQL5Dialect改成org.hibernate.dialect.MySQL8Dialect,方言不匹配会导致JPA表结构校验阶段卡住。
- 先确认本地MySQL服务是否正常启动:Windows系统打开服务面板找到MySQL服务查看运行状态,Linux系统执行
- 第二优先级:排查实体类约束问题
你的Employee实体中employeeCode字段配置了nullable = false, updatable = false的非空约束,但没有给这个字段配置任何自动赋值逻辑。如果之前库中已经生成过employee表,这个字段无默认值又不允许为空,Hibernate执行ddl-auto=update的表结构同步时会直接阻塞。可以先暂时去掉这个字段的非空约束,启动成功后再补充插入前自动生成员工编码的逻辑。 - 第三优先级:排查端口占用
8080端口被其他进程占用时,Spring Boot启动会卡在Tomcat初始化阶段。直接在命令行执行对应命令排查:- Windows:执行
netstat -ano | findstr "8080",查到占用端口的进程PID后,在任务管理器结束对应进程即可 - Mac/Linux:执行
lsof -i:8080,拿到PID后执行kill -9 对应PID释放端口
嫌排查麻烦也可以直接在配置文件加一行server.port=8081,换端口启动测试。
- Windows:执行
最后把启动类移回tn.poulina.EmployeeManager根包,删掉你之前加的自定义@ComponentScan注解,按上面的步骤排查完就能正常启动。
内容的提问来源于stack exchange,提问作者code_slasher
相关产品推荐
相关产品推荐

