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

相关推荐
雨中飘荡的记忆18 小时前
保证金系统入门到实战
java·后端
Nyarlathotep011318 小时前
Java内存模型
java
暮色妖娆丶1 天前
不过是吃了几年互联网红利罢了,我高估了自己
java·后端·面试
NE_STOP1 天前
MyBatis-参数处理与查询结果映射
java
狂奔小菜鸡1 天前
Day40 | Java中的ReadWriteLock读写锁
java·后端·java ee
SimonKing1 天前
JetBrains 用户狂喜!这个 AI 插件让 IDE 原地进化成「智能编码助手」
java·后端·程序员
狂奔小菜鸡1 天前
Day39 | Java中更灵活的锁ReentrantLock
java·后端·java ee
NE_STOP2 天前
MyBatis-配置文件解读及MyBatis为何不用编写Mapper接口的实现类
java
后端AI实验室2 天前
用AI写代码,我差点把漏洞发上线:血泪总结的10个教训
java·ai