Закрытие приложения Spring Boot

Завершение работы приложения Spring Boot

1. обзор

Управление жизненным циклом Spring Boot Application очень важно для готовой к работе системы. Контейнер Spring обрабатывает создание, инициализацию и уничтожение всех компонентов с помощьюApplicationContext.

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

Чтобы узнать больше о том, как настроить проект с помощью Spring Boot, ознакомьтесь со статьейSpring Boot Starter или перейдите кSpring Boot Configuration.

2. Завершение работы конечной точки

По умолчанию все конечные точки включены в приложении Spring Boot Application, кроме/shutdown; это, естественно, часть конечных точекActuator.

Вот зависимость Maven для их настройки:


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

И, если мы хотим настроить поддержку безопасности, нам нужно:


    org.springframework.boot
    spring-boot-starter-security

Наконец, мы включаем конечную точку выключения в файлеapplication.properties:

management.endpoints.web.exposure.include=*
management.endpoint.shutdown.enabled=true
endpoints.shutdown.enabled=true

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

To shut down the Spring Boot application, we simply call a POST method like this:

curl -X POST localhost:port/actuator/shutdown

В этом вызовеport представляет порт привода.

3. Закрыть контекст приложения

Мы также можем вызвать методclose() напрямую, используя контекст приложения.

Начнем с примера создания и закрытия контекста:

ConfigurableApplicationContext ctx = new
  SpringApplicationBuilder(Application.class).web(WebApplicationType.NONE).run();
System.out.println("Spring Boot application started");
ctx.getBean(TerminateBean.class);
ctx.close();

This destroys all the beans, releases the locks, then closes the bean factory. Чтобы проверить завершение работы приложения, мы используем стандартный обратный вызов жизненного цикла Spring с аннотацией@PreDestroy:

public class TerminateBean {

    @PreDestroy
    public void onDestroy() throws Exception {
        System.out.println("Spring Container is destroyed!");
    }
}

Мы также должны добавить компонент этого типа:

@Configuration
public class ShutdownConfig {

    @Bean
    public TerminateBean getTerminateBean() {
        return new TerminateBean();
    }
}

Вот результат выполнения этого примера:

Spring Boot application started
Closing [email protected]
DefaultLifecycleProcessor - Stopping beans in phase 0
Unregistering JMX-exposed beans on shutdown
Spring Container is destroyed!

Здесь важно помнить:while closing the application context, the parent context isn’t affected due to separate lifecycles.

3.1. Закройте текущий контекст приложения

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

Если мы хотим закрыть текущий контекст, одно из решений - просто вызвать конечную точку привода/shutdown.

Однако мы также можем создать нашу собственную конечную точку:

@RestController
public class ShutdownController implements ApplicationContextAware {

    private ApplicationContext context;

    @PostMapping("/shutdownContext")
    public void shutdownContext() {
        ((ConfigurableApplicationContext) context).close();
    }

    @Override
    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
        this.context = ctx;

    }
}

Здесь мы добавили контроллер, который реализует интерфейсApplicationContextAware и переопределяет метод установки для получения текущего контекста приложения. Затем в методе сопоставления мы просто вызываем методclose().

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

curl -X POST localhost:port/shutdownContext

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

4. ВыходSpringApplication

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

Компоненты могут реализовать интерфейсExitCodeGenerator для возврата определенного кода ошибки:

ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Application.class)
  .web(WebApplicationType.NONE).run();

int exitCode = SpringApplication.exit(ctx, new ExitCodeGenerator() {
@Override
public int getExitCode() {
        // return the error code
        return 0;
    }
});

System.exit(exitCode);

Тот же код с применением Java 8 лямбд:

SpringApplication.exit(ctx, () -> 0);

After calling the System.exit(exitCode), the program terminates with a 0 return code:

Process finished with exit code 0

5. Убить процесс приложения

Наконец, мы также можем закрыть Spring Boot Application из-за пределов приложения, используя скрипт bash. Наш первый шаг для этой опции - заставить контекст приложения записать свой PID в файл:

SpringApplicationBuilder app = new SpringApplicationBuilder(Application.class)
  .web(WebApplicationType.NONE);
app.build().addListeners(new ApplicationPidFileWriter("./bin/shutdown.pid"));
app.run();

Затем создайте файлshutdown.bat со следующим содержимым:

kill $(cat ./bin/shutdown.pid)

Выполнениеshutdown.bat извлекает идентификатор процесса из файлаshutdown.pid и использует командуkill для завершения приложения Boot.

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

В этом кратком обзоре мы рассмотрели несколько простых методов, которые можно использовать для завершения работающего приложения Spring Boot.

Пока разработчик должен выбрать подходящий метод; все эти методы следует использовать намеренно и целенаправленно.

Например,.exit() предпочтительнее, когда нам нужно передать код ошибки в другую среду, например JVM, для дальнейших действий. ИспользованиеApplication PID gives more flexibility, as we can also start or restart the application с использованием сценария bash.

Наконец,/shutdown здесь, чтобы сделать возможнымterminate the applications externally via HTTP. Во всех остальных случаях.close() будет работать отлично.

Как обычно, полный код этой статьи доступен наGitHub project.

Related