2011-08-05 3 views
5

J'applique actuellement ServletContextListener et utilise contextDestroyed() pour exécuter des tâches de nettoyage sur mon application Web avant son arrêt. Cependant, j'ai lu sur la façon dont Runtime.addShutdownHook(Thread) peut être utilisé dans le même but.contextDestroyed() vs addShutdownHook()

Y a-t-il une différence entre ces deux méthodes d'exécution du nettoyage avant le déploiement? Qu'est-ce qui est préférable pour une application web, en termes de fonctionnalité, d'efficacité et de maintenabilité?

Répondre

8

Je pense que le ServletContextListener est plus approprié pour une application Web, car vous nettoyez les ressources pour chaque session.

Un hook d'arrêt est exécuté lorsque la JVM est arrêtée. Ce serait quand vous arrêtez votre conteneur, qui est un événement ponctuel.

3

De nombreux conteneurs de servlets prennent en charge des opérations de suppression et/ou de rechargement dynamiques de WAR sans arrêter le processus JVM. Ainsi, si vous écrivez votre routine de nettoyage en tant que ServletContextListener, il pourrait potentiellement être exécuté plusieurs fois pendant la durée de vie du conteneur. (Par exemple, si vous modifiez et rechargez votre WAR plusieurs fois alors que le processus conteneur est toujours actif.)

Cependant, si vous implémentez votre nettoyage à l'aide de Runtime.addShutdownHook, il ne s'exécutera qu'une fois: lorsque la JVM du conteneur dans son ensemble est fermé. ServletContextListener est probablement la bonne solution pour vous, car elle associe votre routine de nettoyage à la durée de vie de l'application Web, contrairement à la durée de vie du processus conteneur qui l'héberge.

+1

+1 merci la distinction est claire pour moi maintenant –

4

Le danger avec l'utilisation de addShutdownHook() est que vous obtiendrez probablement une fuite de classloader qui deviendra apparente lorsque vous redéployez votre application plusieurs fois. Comme la classe du hook d'arrêt (une sous-classe Thread ou une implémentation Runnable dans votre webapp) provient du chargeur de classe de votre webapp, même après que votre webapp n'a pas été déployée par le conteneur, le hook d'arrêt sera toujours enregistré avec le système. Cela signifie que le classloader de l'ensemble de la Webapp ne peut pas être collecté.

Je recommanderais certainement ServletContextListener.

2

La fuite dont nous parlons ne se produira que si nous faisons le chaud/déploiement. Cependant, si le serveur est redémarré après chaque changement de déploiement, le hook devrait fonctionner correctement sans fuite de mémoire. En outre, un autre facteur régissant la fuite est le type de nettoyage des ressources que vous essayez de contrôler via l'écouteur/le crochet.

+3

Ceci est un commentaire à une réponse précédente pas une réponse en soi. –

1

Pourquoi ne pas faire les deux? Alors que ServletContextListener est plus approprié pour une webapp, je trouve que pendant le développement le serveur est souvent arrêté brusquement et ensuite contextDestroyed() n'est jamais appelé, donc vous pouvez avoir les deux mécanismes en place pour vous assurer qu'il y a toujours un shutdown:

Implémentez un ServletContextListener où contextInitialized appelle addShutdownHook() et contextDestroyed appelle removeShutdownHook(). Le hook et contextDestroyed peuvent tous les deux déléguer à une méthode interne pour effectuer le nettoyage. De cette façon, si l'écouteur est invoqué correctement, le hook est ajouté et supprimé (mais pas invoqué) et il n'y a pas de fuite, mais si le serveur meurt sans que le contexte soit détruit, le hook d'arrêt nettoie les choses.