Servlet Listener sind Klassen, die ein Servlet Listener Interface implementieren, im DD der Anwendung dem Container bekannt gemacht werden und bei Lifecycle Ereignissen der Webanwendung vom Container gerufen werden. Listener werden pro Anwendung einmal in der Reihenfolge ihres Erscheinens im DD instanziiert, sie sind Application-Singletons. Die Angabe eines Typs ist nicht notwendig, der Container ermittelt diesen per Introspektion. Die Listenerklasse muss den Standardkonstruktor besitzen, damit der Container eine Instanz zur Abarbeitung des Events erzeugen kann.
<listener> <listener-class> a.b.MyRequestListener </listener-class> </listener>Beim Runterfahren der Anwendung werden erst die Session-Listener, dann die Context-Listener in der umgekehrten Reihenfolge ihres Erscheinens im DD benachrichtigt.
Die Singletoneigenschaft der Listenerinstanzen erzwingt, dass Zustände der entsprechenden Scopes nicht in den Listenerklassen gehalten werden dürfen. Zustände werden am entsprechenden Scope über die setAttribute-Methode hinterlegt. In einer Multithreadumgebung wie der eines Webcontainers werden diese Attribute potenziell nebenläufig geändert. Der Container wird in keiner Weise die Aufrufe unterschiedlicher Requests synchronisieren. Die Listener Implementierungen müssen selbst dafür sorgen und es gilt ähnlich wie für Filter: nichttriviale Listener werden synchronisierten Code enthalten und die Synchronisation erfolgt am entsprechenden Scope. Ein typisches Codefragment für das Setzen eines Zustands im Scope der Session eines Nutzers sieht dann so aus:
.. HttpSession session = event.getSession(); synchronized (session) { session.setAttribute("SOME_STATE", new Integer(1)); } ..In Clusterumgebungen werden Lifecycle Events nicht zwischen den Knoten ausgetauscht.
Servlet Listener für den Lifecycle der Scopes
Es gibt drei Listener für die Lifecycle Ereignisse der drei Scopes:
Scope | Application | Session | Request |
---|---|---|---|
Interface | ServletContextListener | HttpSessionListener | ServletRequestListener |
Ereignis | Starten und Stoppen der Anwendung | Erstellen oder Verwerfen einer HttpSession | Start und Ende eines Requests |
Methoden | contextInitialized/Destroyed | sessionCreated/Destroyed | requestInitialized/Destroyed |
Ereignisobjekt | ServletContextEvent | HttpSessionEvent | ServletRequestEvent |
Objekte für Zustandsänderungen und Synchronisation | ServletContext | HttpSession oder ServletContext | ServletRequest, HttpSession oder ServletContext |
Servlet Listener für den Lifecycle der Scope-Attribute
Über die setAttribute und removeAttribute Methoden der Scopes können dort benamte Objektinstanzen hinterlegt werden, die den Status des entsprechenden Scopes repräsentieren. Für die dabei eintretenden Ereignisse kann man für die drei Scopes Listener anmelden:
Scope | Application | Session | Request |
---|---|---|---|
Interface | ServletContextAttributeListener | HttpSessionAttributeListener | ServletRequestAttributeListener |
Ereignis | Attribut im Scope "Application" (Context) wird hinzugefügt, geändert oder gelöscht | Attribut im Scope "Session" wird hinzugefügt, geändert oder gelöscht | Attribut im Scope "Request" wird hinzugefügt, geändert oder gelöscht |
Methoden | attributeAdded/Removed/Replaced | attributeAdded/Removed/Replaced | attributeAdded/Removed/Replaced |
Ereignisobjekt | ServletContextAttributeEvent | HttpSessionBindingEvent | ServletRequestAttributeEvent |
Synchronisation | ServletContext | HttpSession oder ServletContext | ServletRequest, HttpSession oder ServletContext |
Einen "Servlet"AttributeListener gibt es nicht, denn Servlet-"Attribute" sind einfach Klassenvariablen!
HttpSessionActivationListener und HttpSessionBindingListener
Diese Listener werden direkt von den Attributklassen implementiert. Eine Deklaration im Deployment Deskriptor ist nicht erforderlich, die Klassen werden benachrichtigt, wenn sie als Attribute das entsprechende Interface implementieren.
public interface HttpSessionBindingListener { void valueBound(HttpSessionBindingEvent event); void valueUnbound(HttpSessionBindingEvent event); }
public interface HttpSessionActivationListener { void sessionDidActivate(HttpSessionEvent event); void sessionWillPassivate(HttpSessionEvent event); }