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

相关推荐
C_V_Better13 分钟前
浏览器缓存机制:JavaScript 文件缓存导致 404 错误的解决方案
开发语言·前端·javascript·缓存
ramsey1715 分钟前
jmeter-AES加密
java·jmeter
小救星小杜、16 分钟前
a = b &&c 的含义
开发语言·前端·javascript
59678515417 分钟前
C# ListView设置标题头背景颜色和字体颜色
开发语言·c#
QING61820 分钟前
一文带你搞懂HashSet和TreeSet的区别!!!
android·java·数据结构
#摩斯先生24 分钟前
iOS QLPreviewController预览PDF文件等(Swift)
开发语言·ios·pdf·xcode·swift
QING61828 分钟前
详解:LinkedList的工作原理和实现
android·java·数据结构
QING61830 分钟前
详解:Set集合是如何保证元素不重复的
android·java·数据结构
Lill_bin30 分钟前
Java中的分布式锁:原理、实现与最佳实践
java·开发语言·数据结构·分布式·算法·排序算法·maven
weixin_3077791332 分钟前
Python带多组标签的Snowflake SQL查询批量数据导出程序
开发语言·python·sql