L'utilisation servlet spéciale de démarrage automatique pour initialiser des données de démarrage et l'application d'actions
-
28-09-2019 - |
Question
Je dois obtenir une configuration et se connecter à des ressources externes / objets / systèmes quelque part et le stocker dans champ d'application.
Je vois deux façons de configurer mon application:
- Outrepasser la
init()
dans les servlets existants et le code nécessaire et il garder tous les objets construits à l'intérieur même servlet. - Avoir une sorte d'un servlet d'initialisation et en utilisant son
init()
pour faire le travail. Ensuite, le stockage d'objets créés dansServletContext
pour la partager avec mes autres servlets.
Ce qui précède est de meilleure approche? Y at-il une meilleure façon de partager des objets entre servlets? les appeler directement les uns des autres ou si ...?
La solution
Aucun des deux est la meilleure approche. Servlets sont destinés à écouter les événements HTTP (requêtes HTTP), et non pas sur les événements de déploiement (démarrage / arrêt).
CDI / JSF / EJB indisponible? Utilisez ServletContextListener
@WebListener
public class Config implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
// Do stuff during webapp's startup.
}
public void contextDestroyed(ServletContextEvent event) {
// Do stuff during webapp's shutdown.
}
}
Si vous n'êtes pas sur Servlet 3.0 encore et ne peut pas mettre à niveau et ne peut donc pas utiliser l'annotation @WebListener
, alors vous devez vous inscrire manuellement dans /WEB-INF/web.xml
comme ci-dessous:
<listener>
<listener-class>com.example.Config</listener-class>
</listener>
Pour stocker et obtenir des objets dans le champ d'application (de sorte que tous les servlets peuvent y accéder), utilisez ServletContext#setAttribute()
et #getAttribute()
.
Voici un exemple qui permet au magasin d'auditeur lui-même dans le champ d'application:
public void contextInitialized(ServletContextEvent event) {
event.getServletContext().setAttribute("config", this);
// ...
}
et puis l'obtenir dans un servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
Config config = (Config) getServletContext().getAttribute("config");
// ...
}
Il est également disponible dans JSP EL par ${config}
. Ainsi, vous pouvez faire un haricot simple ainsi.
CDI disponibles? Utilisez @Observes
sur ApplicationScoped.class
import javax.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class Config {
public void init(@Observes @Initialized(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's startup.
}
public void destroy(@Observes @Destroyed(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's shutdown.
}
}
Il est disponible dans un servlet via @Inject
. Faire si nécessaire aussi @Named
il est disponible via #{config}
dans EL ainsi.
A pris note devrait être que ce nouveau depuis CDI 1.1. Si vous êtes toujours sur CDI 1.0 et ne peut pas mettre à niveau, puis choisir une autre approche.
JSF disponible? Utilisez @ManagedBean(eager=true)
import javax.faces.bean.ManagedBean
import javax.faces.bean.ApplicationScoped;
@ManagedBean(eager=true)
@ApplicationScoped
public class Config {
@PostConstruct
public void init() {
// Do stuff during webapp's startup.
}
@PreDestroy
public void destroy() {
// Do stuff during webapp's shutdown.
}
}
Il est disponible via #{config}
dans EL ainsi.
EJB disponible? @Startup
@Singleton
@Startup
@Singleton
public class Config {
@PostConstruct
public void init() {
// Do stuff during webapp's startup.
}
@PreDestroy
public void destroy() {
// Do stuff during webapp's shutdown.
}
}
Il est disponible dans un servlet via @EJB
. Je dis « considérer », parce que vous ne devriez pas abuser d'un EJB pour le bien d'un crochet de démarrage. De plus, un @Singleton
est par défaut de lecture / écriture verrouillé et principalement pour des trucs intented transactionnels tels que les travaux d'arrière-plan de programmation.