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

如何让Spring Boot应用在Windows关机、重启、注销时接收关闭事件?

如何让Spring Boot应用响应Windows关机、重启和注销事件

我懂你的痛点——context.registerShutdownHook()只能捕获手动Ctrl+C的关闭信号,完全拿Windows系统层面的关机、重启、注销操作没办法。下面给你两个实战方案,尤其是把应用部署成Windows服务的方式,这是目前最可靠的解决办法。

方案一:将Spring Boot应用部署为Windows服务(强烈推荐)

这是Windows平台下处理系统级关闭事件的标准姿势,因为Windows服务会在系统关机、重启或注销时收到系统发送的停止指令,Spring Boot可以通过自身的生命周期钩子完美响应这个信号。

步骤1:打包可执行JAR包

先确保你的Spring Boot应用已经打包成可执行JAR——用Maven的话执行mvn package,用Gradle就跑gradle bootJar,生成的JAR包直接就能运行。

步骤2:用WinSW把JAR包装成Windows服务

WinSW是个轻量工具,专门用来把任意可执行程序转成Windows服务,操作很简单:

  • 下载WinSW的对应版本(比如64位系统下的WinSW-x64.exe),把它重命名成和你的应用相关的名字,比如my-spring-boot-app.exe。
  • 在同一个目录下创建一个同名的XML配置文件(比如my-spring-boot-app.xml),配置内容参考下面的示例,记得替换成你自己的路径和参数:
<service>
  <id>MySpringBootService</id>
  <name>我的Spring Boot应用服务</name>
  <description>把Spring Boot应用作为Windows系统服务运行</description>
  <executable>java</executable>
  <arguments>-jar "D:\projects\my-app\target\my-app-1.0.0.jar"</arguments>
  <logpath>D:\projects\my-app\logs</logpath>
  <logmode>rotate</logmode> <!-- 日志自动轮转 -->
  <onfailure>restart</onfailure> <!-- 服务崩溃时自动重启 -->
</service>
  • 以管理员身份打开命令提示符,进入到这个目录,执行安装命令:
    my-spring-boot-app.exe install
  • 启动服务:my-spring-boot-app.exe start

步骤3:在Spring Boot中编写关闭逻辑

你可以通过实现DisposableBean接口,或者用@PreDestroy注解来定义关闭时要执行的操作,当Windows服务收到停止信号时,Spring会自动触发这些方法:

实现接口的方式:

@Component
public class AppShutdownHandler implements DisposableBean {

    @Override
    public void destroy() throws Exception {
        // 这里写你的关闭逻辑:比如释放数据库连接、保存缓存数据、发送通知等
        System.out.println("收到Windows系统停止信号,正在执行应用清理操作...");
    }
}

或者用更简洁的注解方式:

@Component
public class AppShutdownHandler {

    @PreDestroy
    public void onAppShutdown() {
        // 自定义关闭逻辑
        System.out.println("应用即将关闭,开始执行收尾任务...");
    }
}

当Windows执行关机、重启或注销操作时,系统会先给所有运行的服务发送停止指令,你的Spring Boot应用就能稳稳捕获到这个信号,执行你定义的清理逻辑。

方案二:用JVM Shutdown Hook临时处理(仅适合测试)

如果只是临时测试,不想折腾服务部署,可以试试手动添加JVM级别的Shutdown Hook,但这个方案可靠性不如服务——比如Windows强制关机时,可能不会等JVM执行完钩子逻辑就直接结束进程。

在Spring Boot主类里添加这段代码:

@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(MyApplication.class, args);

        // 添加JVM shutdown hook
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("捕获到系统关闭信号,开始关闭应用上下文...");
            context.close();
            // 这里可以加更多自定义清理逻辑
        }));
    }
}

不过要注意,当应用作为普通控制台程序运行时,Windows注销或关机时可能会弹出提示框,问要不要强制关闭程序,如果用户点了立即关闭,钩子逻辑可能来不及执行。所以这个方案只适合临时验证,生产环境一定要用服务方式。

验证方式

部署成服务后,直接重启Windows系统,然后去应用的日志目录里看日志,确认destroy()或者@PreDestroy方法里的内容有没有被执行,就知道是否生效了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:52:25