java:spring boot程序怎么优雅关闭

项目【myWeb】

【pom.xml】

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.3.12.RELEASE</version>
</dependency>

【application.properties】

bash 复制代码
server.port=8080
spring.application.name=myWeb

【MyWebTest.java】

java 复制代码
package com.chz.myWeb;

@SpringBootApplication()
public class MyWebTest {

    public static void main(String[] args) {
        registerHook();
        SpringApplication.run(MyWebTest.class, args);
    }

    private static void registerHook() {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            // 当pod关闭的时候会触发这个回调
            System.out.println(LocalDateTime.now() + "-->Hook.run 1....");
            // 关闭spring boot
            ShutdownHelper.shutdown();
            System.out.println(LocalDateTime.now() + "-->Hook.run 2....");
        }));
    }
}

【TestController.java】

java 复制代码
package com.chz.myWeb.controller;

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {

    // 当【applicationContext.close()】被调用的时候这些destroy方法会被调用
    @PreDestroy
    private void destroyBean()
    {
        System.out.println("TestController::destroyBean start");
        try {
            // 如果某个队列里面有很多的数据,我们可以在这里调用队列的方法让线程阻塞至队列数据被全部发出去。
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
        }
        System.out.println("TestController::destroyBean end");
    }

    @GetMapping("/shutdown")
    public String shutdown() {
        // 这里直接调用关闭
        ShutdownHelper.shutdown();
        return "shutdown";
    }
}

【ShutdownHelper.java】

java 复制代码
package com.chz.myWeb.helper;

@Component
public class ShutdownHelper implements ApplicationContextAware {

    @Autowired
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public static void shutdown() {
        new Thread(()->{
            if( applicationContext instanceof ConfigurableApplicationContext){
                // 这里调用了applicationContext.close之后spring boot的接口就不会再接收请求了
                ((ConfigurableApplicationContext) applicationContext).close();
            }
        }).start();
    }
}

【ThreadTestComponent.java】

java 复制代码
package com.chz.myWeb.helper;

@Component
public class ThreadTestComponent {

    private static Thread testThread = null;

    @PostConstruct
    private void init()
    {
        testThread = new Thread(()->{
            while(true){
                try {
                    System.out.println("ThreadTestComponent::startTestThread()");
                    Thread.sleep(5000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        });
        testThread.start();
    }

    @PreDestroy
    private void destroy()
    {
        System.out.println("ThreadTestComponent::destroy()");
        // 这种自己创建的线程在【application.close()】被调用时是不会自动关闭的,需要手动关闭。
        testThread.interrupt();
    }
}

试调用一下【http://localhost:8080/test/shutdown】

说明调用【applicationContext.close()】确定可以优雅关闭spring boot程序。

不过线上我们肯定不会去调用这样一个接口,线上pod在关闭的时候会调用【ShutdownHook】,然后在那里调用【applicationContext.close()】就可以了。

相关推荐
人道领域12 分钟前
【LeetCode刷题日记】131.分割回文串,动态规划优化
java·开发语言·leetcode
z落落24 分钟前
C# 接口 interface (多接口实现、类+接口、成员重名)
java·开发语言
发际线向北29 分钟前
0x05 深入了解JVM虚拟机(JVM方法调用 -Ⅰ)
java
宋哥转AI33 分钟前
学了Spring AI Graph再看LangGraph,发现API几乎一模一样
java·人工智能·agent
AskHarries1 小时前
Workspace:文件系统、项目上下文和执行边界
java·服务器·前端
摇滚侠1 小时前
JavaWeb 全套教程 Servlet 66-74
java·servlet·tomcat·intellij-idea·jar
Solis程序员1 小时前
滑动窗口热键探测与三级缓存设计
java·spring·缓存
好家伙VCC1 小时前
区块链双向支付通道实战:从签名到结算
java·后端·区块链·asp.net
知识的宝藏2 小时前
Xpaht self::div 轴语法
开发语言
keykey6.2 小时前
卷积神经网络(CNN):让AI学会“看“
开发语言·人工智能·深度学习·机器学习