Arrêter une application de démarrage de printemps

Fermer une application de démarrage de printemps

1. Vue d'ensemble

La gestion du cycle de vie de Spring Boot Application est très importante pour un système prêt à la production. Le conteneur Spring gère la création, l'initialisation et la destruction de tous les Beans à l'aide desApplicationContext.

Le point fort de cet article est la phase de destruction du cycle de vie. Plus précisément, nous examinerons différentes façons d'arrêter une application Spring Boot.

Pour en savoir plus sur la configuration d'un projet à l'aide de Spring Boot, consultez l'articleSpring Boot Starter ou passez en revue lesSpring Boot Configuration.

2. Point final d'arrêt

Par défaut, tous les points de terminaison sont activés dans Spring Boot Application à l'exception de/shutdown; cela fait naturellement partie des points de terminaisonActuator.

Voici la dépendance Maven pour les configurer:


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

Et, si nous voulons également mettre en place un support de sécurité, nous avons besoin de:


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

Enfin, nous activons le point de terminaison d'arrêt dans le fichierapplication.properties:

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

Notez que nous devons également exposer les points de terminaison d'actionneur que nous souhaitons utiliser. Dans l'exemple ci-dessus, nous avons exposé tous les points de terminaison de l'actionneur qui incluront le point de terminaison/shutdown.

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

curl -X POST localhost:port/actuator/shutdown

Dans cet appel, leport représente le port de l'actionneur.

3. Fermer le contexte d'application

Nous pouvons également appeler la méthodeclose() directement en utilisant le contexte de l'application.

Commençons par un exemple de création d'un contexte et de sa fermeture:

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. Pour vérifier l'arrêt de l'application, nous utilisons le rappel de cycle de vie standard de Spring avec l'annotation@PreDestroy:

public class TerminateBean {

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

Nous devons également ajouter un haricot de ce type:

@Configuration
public class ShutdownConfig {

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

Voici la sortie après avoir exécuté cet exemple:

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

La chose importante à garder à l'esprit ici:while closing the application context, the parent context isn’t affected due to separate lifecycles.

3.1. Fermer le contexte d'application actuel

Dans l'exemple ci-dessus, nous avons créé un contexte d'application enfant, puis utilisé la méthodeclose() pour le détruire.

Si nous voulons fermer le contexte courant, une solution est d'appeler simplement le point final de l'actionneur/shutdown.

Cependant, nous pouvons également créer notre propre point de terminaison personnalisé:

@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;

    }
}

Ici, nous avons ajouté un contrôleur qui implémente l'interfaceApplicationContextAware et remplace la méthode setter pour obtenir le contexte actuel de l'application. Ensuite, dans une méthode de mappage, nous appelons simplement la méthodeclose().

Nous pouvons ensuite appeler notre nouveau point de terminaison pour fermer le contexte actuel:

curl -X POST localhost:port/shutdownContext

Bien entendu, si vous ajoutez un point de terminaison comme celui-ci dans une application réelle, vous souhaiterez également le sécuriser.

4. SortieSpringApplication

SpringApplication enregistre un hookshutdown auprès de la machine virtuelle Java pour s'assurer que l'application se ferme correctement.

Les beans peuvent implémenter l'interfaceExitCodeGenerator pour renvoyer un code d'erreur spécifique:

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);

Le même code avec l'application de Java 8 lambdas:

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. Tuez le processus d'application

Enfin, nous pouvons également arrêter une application de démarrage Spring en dehors de l'application à l'aide d'un script bash. Notre première étape pour cette option consiste à demander au contexte de l'application d'écrire son PID dans un fichier:

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

Ensuite, créez un fichiershutdown.bat avec le contenu suivant:

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

L'exécution deshutdown.bat extrait l'ID de processus du fichiershutdown.pid et utilise la commandekill pour terminer l'application de démarrage.

6. Conclusion

Dans cet article rapide, nous avons couvert quelques méthodes simples qui peuvent être utilisées pour arrêter une application Spring Boot en cours d'exécution.

Il appartient au développeur de choisir une méthode appropriée; toutes ces méthodes doivent être utilisées volontairement et volontairement.

Par exemple,.exit() est préférable lorsque nous devons transmettre un code d'erreur à un autre environnement, disons JVM pour d'autres actions. Utilisation deApplication PID gives more flexibility, as we can also start or restart the application avec l'utilisation du script bash.

Enfin,/shutdown est là pour permettre determinate the applications externally via HTTP. Dans tous les autres cas,.close() fonctionnera parfaitement.

Comme d'habitude, le code complet de cet article est disponible sur lesGitHub project.