Подтвердить что ты не робот

Spring Загрузка - Подождите, пока веб-сервер запустится

В моем загрузочном приложении Spring мне нужно дождаться, когда веб-сервер (по умолчанию Tomcat) будет полностью инициализирован и готов к трафику, прежде чем отправлять сообщения другим приложениям, сообщающим им отправлять HTTP-запросы мне (в частности, систему мониторинга который попадает на мой /health).

Я попытался поместить логику, которая отправляет сообщения другим приложениям в ApplicationListener<ContextRefreshedEvent>, но все еще слишком рано. Другие приложения пытаются запросить меня и провалиться. Прямо сейчас я положил задержку в onApplicationEvent, и это работает, но оно взломанно и racy.

Я также попытался добавить ServletContextInitializer, но уволился еще раньше.

Я предполагаю, что мне нужно использовать Tomcat API, но я хотел посмотреть, есть ли что-то в Boot API для этого.

4b9b3361

Ответ 1

Самое простое, что нужно сделать, это отправить сообщение, как только SpringApplication.run() вернется. Этот метод не вернется, пока Tomcat (или любой другой поддерживаемый встроенный контейнер) не будет полностью запущен и не прослушивает настроенные порты. Однако, хотя это и просто, но это не очень аккуратный подход, так как он сочетает в себе проблемы вашего основного класса конфигурации и некоторую логику времени выполнения вашего приложения.

Вместо этого вы можете использовать SpringApplicationRunListener. finished() не будет вызываться до тех пор, пока 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) { }

Ответ 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-<profile_name>.properties

context.listener.classes=com.example.MyApplicationListener