Spring Boot - 等待 Web 服务器启动

Posted

技术标签:

【中文标题】Spring Boot - 等待 Web 服务器启动【英文标题】:Spring Boot - Wait for web server to start 【发布时间】:2015-03-30 04:41:03 【问题描述】:

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

我尝试将向其他应用程序发送消息的逻辑放在ApplicationListener<ContextRefreshedEvent> 中,但现在还为时过早。其他应用程序尝试向我提出请求并失败。现在我已经在onApplicationEvent 中放了一个延迟,这很有效,但它很老套而且很活泼。

我也尝试添加ServletContextInitializer,但它更早触发了。

我假设我需要使用 Tomcat API,但我想看看 Boot API 中是否有相关内容。

【问题讨论】:

你看到了吗:***.com/a/4747639/283084?此外,也许您可​​以将您的应用隐藏在 LB 后面,并且 LB 不会将您的应用放入其池中,直到对 /health 的请求返回 HTTP OK (200)。 【参考方案1】:

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

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

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

org.springframework.boot.SpringApplicationRunListener=com.example.MyRunListener

使用所需的构造函数创建您的运行侦听器并实现SpringApplicationRunListener。例如:

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;

public class MyRunListener implements SpringApplicationRunListener 

    public MyRunListener(SpringApplication application, String[] args)  

    @Override
    public void starting()  

    @Override
    public void environmentPrepared(ConfigurableEnvironment environment)  

    @Override
    public void contextPrepared(ConfigurableApplicationContext context)  

    @Override
    public void contextLoaded(ConfigurableApplicationContext context)  

    @Override
    public void started(ConfigurableApplicationContext context) 
        // Send message; Tomcat is running and listening on the configured port(s)
    

    @Override
    public void running(ConfigurableApplicationContext context)  

    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception)  

【讨论】:

效果很好。我创建了另一个感兴趣的 bean 可以实现的接口,我的 SpringApplicationRunListener 将它们拉出上下文并调用它们,因此逻辑可以保留在相关 bean 中。 这对我根本不起作用。在应用程序启动和运行之前,finished() 方法几乎立即被调用。 @onnoweb 我看不出这是如何发生的,因为在 SpringApplication.run 处理结束时调用了完成的方法。也许您可以使用minimal, complete, and verifiable example 提出您自己的问题,该问题显示已完成的调用比预期的要早。 我缩小了我的问题范围:ApplicationReadyEvent 在 Tomcat 启动并运行之前被触发。使用 CommandLineRunner 而不是监听 ApplicationReadyEvent 解决了我的问题。 此界面已更新;较新的实现现在应该使用running 方法。【参考方案2】:

从 Spring Boot 1.3.0 开始,这也可以通过实现 ApplicationListener<ApplicationReadyEvent> 来完成

示例:

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;
    

此外,如已接受的答案中所述,您可以创建一个名为 src/main/resources/META-INF/spring.factories 的文件,列出您的 ApplicationListener。例如:

org.springframework.context.ApplicationListener=com.example.MyApplicationListener

但是,在我的例子中,我只需要这个监听器在特定的配置文件下运行

所以我将以下属性添加到application-&lt;profile_name&gt;.properties

context.listener.classes=com.example.MyApplicationListener

【讨论】:

以上是关于Spring Boot - 等待 Web 服务器启动的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot Dubbo 应用启停源码分析

Spring Boot 定时任务,怎么实现任务动态增删启停?

Spring Boot 定时任务,怎么实现任务动态增删启停?

Spring Boot Webclient - 等待多呼叫的结束响应

SFA官方翻译Spring Boot中配置Tomcat连接池

Spring Boot系列教程七:Spring boot集成MyBatis