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()】就可以了。

相关推荐
鹿角片ljp5 小时前
LeetCode 64:最小路径和复盘|二维 DP 与 ACM 模式完整写法
java·数据结构·算法
aramae5 小时前
模拟实现strcmp()(C语言)
c语言·开发语言·后端
+VX:Fegn08956 小时前
计算机毕业设计|基于springboot + vue蛋糕店管理系统(源码+数据库+文档)
前端·数据库·vue.js·spring boot·课程设计
泡海椒6 小时前
PDF 表格样式优化:jquick-pdf 边框、圆角、背景色
java·开发语言·pdf
Beyond_System|系统之外7 小时前
【学编程】Python基础编程题100道(21-60)
开发语言·python·算法
景熙55238 小时前
15.Java 8 Stream 流入门到实战
java·开发语言·数据结构
wno7048 小时前
Spring Security权限控制
java·python·spring
wno7048 小时前
Spring Boot整合Kafka
spring boot·kafka
杨运交9 小时前
[071][验证码模块]基于Spring拦截器的验证码认证设计思想
java·后端·spring