Programmatically Restarting a Spring Boot Application

Программный перезапуск приложения Spring Boot

1. обзор

В этом руководстве мы покажем, какprogrammatically restart a Spring Boot application.

Перезапуск нашего приложения может быть очень удобным в некоторых случаях:

  • Перезагрузка конфигурационных файлов при изменении какого-либо параметра

  • Изменение текущего активного профиля во время выполнения

  • Повторная инициализация контекста приложения по любой причине

Хотя в этой статье рассматривается функциональность перезапуска приложения Spring Boot, обратите внимание, что у нас также есть отличный учебник поshutting down Spring Boot applications.

Теперь давайте рассмотрим различные способы реализации перезапуска приложения Spring Boot.

2. Начните заново, создав новый контекст

Мы можем перезапустить наше приложение, закрыв контекст приложения и создав новый контекст с нуля. Хотя этот подход довольно прост, есть некоторые тонкие детали, с которыми мы должны быть осторожны, чтобы заставить его работать.

Давайте посмотрим, как это реализовать в методеmain нашего приложения Spring Boot:

@SpringBootApplication
public class Application {

    private static ConfigurableApplicationContext context;

    public static void main(String[] args) {
        context = SpringApplication.run(Application.class, args);
    }

    public static void restart() {
        ApplicationArguments args = context.getBean(ApplicationArguments.class);

        Thread thread = new Thread(() -> {
            context.close();
            context = SpringApplication.run(Application.class, args.getSourceArgs());
        });

        thread.setDaemon(false);
        thread.start();
    }
}

Как мы видим в приведенном выше примере, важно воссоздать контекст в отдельном не-демоническом потоке - таким образом мы предотвращаем завершение работы JVM, вызванное методомclose, от закрытия нашего приложения. В противном случае наше приложение остановится, поскольку JVM не ожидает завершения потоков демона перед их завершением.

Кроме того, давайте добавим конечную точку REST, через которую мы можем запустить перезапуск:

@RestController
public class RestartController {

    @PostMapping("/restart")
    public void restart() {
        Application.restart();
    }
}

Здесь мы добавили контроллер с методом сопоставления, который вызывает наш методrestart.

Затем мы можем вызвать нашу новую конечную точку, чтобы перезапустить приложение:

curl -X POST localhost:port/restart

Конечно, если мы добавим такую ​​конечную точку в реальное приложение, нам также придется защитить ее.

3. Конечная точка перезапуска привода

Другой способ перезапустить наше приложение - использовать встроенныйRestartEndpoint изSpring Boot Actuator.

Во-первых, давайте добавим необходимые зависимости Maven:


    org.springframework.boot
    spring-boot-starter-actuator


    org.springframework.boot
    spring-cloud-starter

Затем мы должны включить встроенную конечную точку перезапуска в нашем файлеapplication.properties:

management.endpoint.restart.enabled=true

Теперь, когда мы все настроили, мы можем внедритьRestartEndpoint in в нашу службу:

@Service
public class RestartService {

    @Autowired
    private RestartEndpoint restartEndpoint;

    public void restartApp() {
        restartEndpoint.restart();
    }
}

В приведенном выше коде мы используемRestartEndpoint bean для перезапуска нашего приложения. Это хороший способ перезапуска, потому что нам нужно вызвать только один метод, который выполняет всю работу.

Как мы видим, использованиеRestartEndpoint - это простой способ перезапустить наше приложение. С другой стороны, у этого подхода есть недостаток, поскольку он требует добавления упомянутых библиотек. Если мы их еще не используем, это может быть слишком много накладных расходов только для этой функции. В этом случае мы можем придерживаться ручного подхода из предыдущего раздела, так как для этого требуется всего несколько строк кода.

4. Обновление контекста приложения

В некоторых случаях мы можем перезагрузить контекст приложения, вызвав его методrefresh.

Хотя этот метод может показаться многообещающим, только некоторые типы контекста приложения поддерживают обновление уже инициализированного контекста. Например,FileSystemXmlApplicationContext,GroovyWebApplicationContext, и некоторые другие поддерживают его.

К сожалению, если мы попробуем это в веб-приложении Spring Boot, мы получим следующую ошибку:

java.lang.IllegalStateException: GenericApplicationContext does not support multiple refresh attempts:
just call 'refresh' once

Наконец, хотя есть некоторые типы контекста, которые поддерживают множественные обновления, мы должны избегать этого. Причина в том, что методrefresh разработан как внутренний метод, используемый платформой для инициализации контекста приложения.

5. Заключение

В этой статье мы рассмотрели несколько различных способов, как программно перезапустить приложение Spring Boot.

Как всегда, мы можем найти исходный код примеров наGitHub.