ContextClosedEvent不执行

如何在springboot执行项目停止操作(kill pid)之前,调用外部的restful接口,并且此时项目的各个类的生命周期都还没被杀死,求指点

可以在Spring Boot项目中使用Java的Runtime类来执行系统命令,从而调用外部的RESTful接口。具体步骤如下:

  1. 在Spring Boot项目中创建一个ShutdownHook类,该类实现了Java的Runnable接口,并在run方法中调用外部RESTful接口。
public class ShutdownHook implements Runnable {
    private String url;

    public ShutdownHook(String url) {
        this.url = url;
    }

    @Override
    public void run() {
        try {
            URL obj = new URL(url);
            HttpURLConnection con = (HttpURLConnection) obj.openConnection();
            con.setRequestMethod("GET");
            int responseCode = con.getResponseCode();
            System.out.println("ShutdownHook executed, response code: " + responseCode);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  1. 在Spring Boot项目的启动类中添加ShutdownHook,在项目停止时调用该类的run方法。
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Application.class);
        app.addListeners(new ApplicationPidFileWriter());
        app.addListeners(new ShutdownHook("http://localhost:8080/api/shutdown"));
        app.run(args);
    }
}
  1. 在Spring Boot项目中添加一个RESTful接口,用于接收停止命令并执行停止操作。
@RestController
@RequestMapping("/api")
public class ShutdownController {
    @GetMapping("/shutdown")
    public void shutdown() {
        System.out.println("ShutdownController executed");
        System.exit(0);
    }
}
  1. 在命令行中执行kill命令,停止Spring Boot项目。
kill -15 <pid>

在执行kill命令时,Spring Boot项目会先执行ShutdownHook类的run方法,调用外部RESTful接口。然后再执行Spring Boot项目的停止操作,最后执行ShutdownController类的shutdown方法,完成项目的停止操作。

使用@PreDestroy注解来标注一个生命周期方法,它会在Spring容器销毁bean之前调用。在这个方法中调用外部的RESTful接口。
示例代码:


@Service
public class MyService {

  @PreDestroy
  public void onDestroy() {
    // 在这里调用外部的RESTful接口
    String url = "http://example.com/api/stop";
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.postForObject(url, null, Void.class);
  }

}

MyService是一个Spring的服务类,它的onDestroy()方法会在Spring容器销毁MyService实例之前被调用。在这个方法中,使用RestTemplate来向外部的RESTful接口发送了一个POST请求。
当需要停止Spring Boot项目时,可以使用kill pid命令来杀死进程,此时Spring Boot项目的各个类的生命周期都还没被杀死,因此@PreDestroy注解所标注的方法也会被调用。

我理解你的意思是想在spring boot 的生命周期某些钩子方法中执行 一个外部请求。你可以了解一下spring boot 提供的一些可以的接口。你写的那个按道理是会执行的,看下你是否加了正确的注解或者spring 是否能扫描到。或者你的关闭命令是 kill -9.
我写一些示例,你可以参考一下,Spring Boot中使用生命周期方法:

@Component
public class MyBean implements InitializingBean,DisposableBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        // 在Bean初始化后执行一些初始化操作
        System.out.println("MyBean初始化完成");
    }

    @Override
    public void destroy() throws Exception {
        // 在Bean销毁前执行一些清理操作
        System.out.println("MyBean销毁完成");
    }

    @PostConstruct
    public void init() {
        // 在Bean初始化后执行一些初始化操作
        System.out.println("MyBean初始化完成");
    }

    @PreDestroy
    public void cleanup() {
        // 在Bean销毁前执行一些清理操作
        System.out.println("MyBean销毁完成");
    }

   } 

SmartLifecycle

    @Component
    public static class MySmartLifecycle implements SmartLifecycle {

        private boolean running = false;

        @Override
        public void start() {
            // 在应用程序启动时执行
            System.out.println("MySmartLifecycle开始启动");
            running = true;
        }

        @Override
        public void stop() {
            // 在应用程序关闭时执行
            System.out.println("MySmartLifecycle开始停止");
            running = false;
        }

        @Override
        public boolean isRunning() {
            return running;
        }

        @Override
        public int getPhase() {
            return 0;
        }
    }

    @EventListener
    public void handleContextRefreshed(ContextRefreshedEvent event) {
        // 在ApplicationContext初始化或刷新时执行一些初始化操作
        System.out.println("ApplicationContext初始化或刷新完成");
    }

    @EventListener
    public void handleContextClosed(ContextClosedEvent event) {
        // 在ApplicationContext关闭时执行一些清理操作
        System.out.println("ApplicationContext关闭完成");
    }
}