SpringBoot之优雅关闭系统

☆樱花仙子☆ 提交于 2020-02-03 12:20:03

在使用SpringBoot的时候,通常情况下,我都是使用ps -ef | grep java 找到对于的服务器id,然后通过kill -9 进程号进行删除的,这样会导致正在进行的进程也会被关闭,而没有将目前的工作进行保存,最近看到一篇文章,也就自己进行尝试,参考链接放在了最后面

  1. 通过SpringBoot提供的actuator
    actuator提供审计,健康检查,HTTP跟踪等功能,能够帮助我们监控和管理SpringBoot,在这里他提供了执行shutdown的功能
<!--  添加依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>


#在application.yml 中进行配置,shutdown默认是关闭的,这里需要将其设置为true,同时将接口暴露出来到web上
management:
  endpoint:
    shutdown:
      enabled: true
  endpoints:
    web:
      exposure:
        include: shutdown


// 配置controller
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PreDestroy;

@RestController
public class EpidemicController {

    private static final Logger logger = LoggerFactory.getLogger(EpidemicController.class);

    @Test
    @GetMapping("/test")
    public String test(){
        return "test";
    }
	//  为控制类定义对应的销毁方法
    @PreDestroy
    public void preDestroy(){
        System.out.print("controller is destroy");
    }

}

启动并访问测试接口,访问正常
启动并访问接口
使用post访问actuator提供的关闭接口,这里我用idea的控制台进行post访问

curl -X POST http://localhost:8081/epidemic/actuator/shutdown

关闭成功
系统正常退出,并且调用了定义好的销毁方法
在这里插入图片描述
2. 获取程序启动时候的context,然后关闭主程序启动时的context

// 构建application的时候,将启动时的ConfigurableApplicationContext保存为静态变量,然后在接口中进行关闭


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class EpidemicApplication {
    public static ConfigurableApplicationContext ctx;
    public static void main(String[] args) {
        ctx = SpringApplication.run(EpidemicApplication.class,args);
    }
}

import cn.edu.dgut.EpidemicApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PreDestroy;

@RestController
public class EpidemicController {

    private static final Logger logger = LoggerFactory.getLogger(EpidemicController.class);

    @GetMapping("/test")
    public String test(){
        return "test";
    }

    @PreDestroy
    public void preDestroy(){
        System.out.print("controller is destroy");
    }

// 在接口中调用的时候进行关闭

    @GetMapping("/shutdown")
    public void shutdown(){
        System.out.print("shutdown project");
        EpidemicApplication.ctx.close();
    }

}

结果:程序正常退出
在这里插入图片描述
3. SpringBoot启动的时候将进程号写入一个app.pid文件

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.ApplicationPidFileWriter;

@SpringBootApplication
public class EpidemicApplication {

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(EpidemicApplication.class);
        // 添加一个pid监听器,将pid写入文件中
        application.addListeners(new ApplicationPidFileWriter("/root/java/test/app.pid"));
        application.run(args);
    }

}

通过cat /root/java/test/app.pid | xargs kill将程序关闭
在这里插入图片描述
参考链接:https://mp.weixin.qq.com/s/oDVaem4rY8AemFEgIZEfdQ

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!