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

相关推荐
牢七几秒前
jfinal_cms-v5.1.0 白盒 nday
开发语言·python
zs宝来了4 分钟前
Spring Boot Starter 机制:如何编写自定义 Starter
spring boot·starter·最佳实践·自定义启动器
ayt00711 分钟前
Netty 4.2核心类解析:SingleThreadIoEventLoop的设计哲学与实现
java·网络
无名-CODING13 分钟前
Java 爬虫进阶:动态网页、多线程与 WebMagic 框架实战
java·爬虫·okhttp
weixin_7042660515 分钟前
Spring 注解驱动开发与 Spring Boot 核心知识点梳理
java·spring boot·spring
开开心心就好15 分钟前
伪装文件历史记录!修改时间的黑科技软件
java·前端·科技·r语言·edge·pdf·语音识别
8Qi818 分钟前
Redis哨兵模式(Sentinel)深度解析
java·数据库·redis·分布式·缓存·sentinel
词元Max21 分钟前
2.5 Python 类型注解与运行时类型检查
开发语言·python
wangchunting25 分钟前
数据结构-树
java·数据结构
无籽西瓜a28 分钟前
【西瓜带你学设计模式 | 第五期 - 建造者模式】建造者模式 —— 产品构建实现、优缺点与适用场景及模式区别
java·后端·设计模式·软件工程·建造者模式