Tomcat Spring启动-等待web服务器启动

Tomcat Spring启动-等待web服务器启动,tomcat,spring-boot,Tomcat,Spring Boot,在我的Spring Boot应用程序中,我需要等待(默认Tomcat)web服务器完全初始化并准备好接收流量,然后再向其他应用程序发送消息,告诉它们向我发送HTTP请求(特别是一个点击我的/health)的监控系统) 我曾尝试将向其他应用程序发送消息的逻辑放在ApplicationListener中,但现在还为时过早。其他应用程序试图向我发出请求,但失败了。现在,我在applicationEvent的中延迟了一段时间,这是可行的,但它很有黑客味 我还尝试添加了一个ServletContextIn

在我的Spring Boot应用程序中,我需要等待(默认Tomcat)web服务器完全初始化并准备好接收流量,然后再向其他应用程序发送消息,告诉它们向我发送HTTP请求(特别是一个点击我的
/health
)的监控系统)

我曾尝试将向其他应用程序发送消息的逻辑放在
ApplicationListener
中,但现在还为时过早。其他应用程序试图向我发出请求,但失败了。现在,我在applicationEvent的
中延迟了一段时间,这是可行的,但它很有黑客味

我还尝试添加了一个
ServletContextInitializer
,但它甚至更早就启动了


我假设我需要使用Tomcat API,但我想看看启动API中是否有用于此的内容。

最简单的方法是在返回
SpringApplication.run()
后发送消息。在Tomcat(或任何其他受支持的嵌入式容器)完全启动并侦听配置的端口之前,此方法不会返回。然而,尽管这很简单,但它并不是一种很好的方法,因为它混合了主配置类的关注点和应用程序的一些运行时逻辑

相反,您可以使用
finished()
在Tomcat完全启动并在配置的端口上侦听之前不会被调用

创建一个名为
src/main/resources/META-INF/spring.factories的文件,列出您的运行侦听器。例如:

org.springframework.boot.SpringApplicationRunListener=com.example.MyRunListener
org.springframework.context.ApplicationListener=com.example.MyApplicationListener
使用所需的构造函数创建运行侦听器,并实现
SpringApplicationRunListener
。例如:

org.springframework.boot.SpringApplicationRunListener=com.example.MyRunListener
org.springframework.context.ApplicationListener=com.example.MyApplicationListener
package.com.example;
导入org.springframework.boot.SpringApplication;
导入org.springframework.boot.SpringApplicationRunListener;
导入org.springframework.context.ConfigurableApplicationContext;
导入org.springframework.core.env.ConfigurableEnvironment;
公共类MyRunListener实现SpringApplicationRunListener{
公共MyRunListener(SpringApplication应用程序,字符串[]args){}
@凌驾
public void start(){}
@凌驾
public void environment已准备就绪(可配置环境){}
@凌驾
public void contextPrepared(ConfigurableApplicationContext上下文){}
@凌驾
public void contextLoaded(ConfigurableApplicationContext上下文){}
@凌驾
public void已启动(ConfigurableApplicationContext上下文){
//发送消息;Tomcat正在运行并在配置的端口上侦听
}
@凌驾
public void正在运行(ConfigurableApplicationContext上下文){}
@凌驾
public void失败(ConfigurableApplicationContext上下文,可丢弃异常){}

自Spring Boot 1.3.0以来,这也可以通过实现
ApplicationListener

例如:

public class MyApplicationListener implements ApplicationListener<ApplicationReadyEvent>, Ordered {

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        //do stuff now that application is ready
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}
然而,在我的例子中,我只需要在特定的配置文件下运行这个侦听器

因此,我将以下属性添加到
application-.properties

context.listener.classes=com.example.MyApplicationListener

您是否看到:?此外,您可以将您的应用程序隐藏在LB后面,LB不会将您的应用程序放入其池中,直到对
/health
的请求返回HTTP OK(200).Works很棒。我创建了另一个感兴趣的bean可以实现的接口,我的
SpringApplicationRunListener
将它们从上下文中提取出来并调用它们,这样逻辑就可以保留在相关的bean中。这对我根本不起作用。finished()方法几乎是立即调用的,而且肯定是在应用程序启动和运行之前调用的。@onnoweb我看不出这会发生什么,因为在
SpringApplication的末尾调用finished方法。运行
处理。也许你可以问自己一个问题,显示finished比预期的更早被调用。我缩小了范围d关闭我的问题:ApplicationReadyEvent在Tomcat启动和运行之前被触发。使用CommandLineRunner而不是侦听ApplicationReadyEvent修复了我的问题。此接口已更新;较新的实现现在应该使用
running
方法。