Listeners play a crucial role in the Java ecosystem, appearing extensively in both Android development and JavaWeb applications. Similar concepts exist in other programming languages, and those familiar with design patterns will find it straightforward to grasp their implementation principles. For developers, utilizing the observer pattern simply requires implementing corresponding interfaces, making it quite convenient. In Servlet 2.5, there are eight types of listeners: six related to the creation and destruction of Session, Request, and Context objects, along with their atribute changes, and two specifically for monitoring objects within sessions.
Object Creation and Destruction Monitoring
ServletRequestListener
This listener monitors the lifecycle of HTTP requests. The requestInitialized(ServletRequestEvent sre) method executes with each incoming request, while requestDestroyed(ServletRequestEvent sre) runs just before the request object is discarded.
The ServletRequestEvent API provides access to getServletContext() which retrieves the current servlet context.
HttpSessionListener
This component tracks session lifecycle events. When a new session is created, sessionCreated(HttpSessionEvent se) is invoked, and sessionDestroyed(HttpSessionEvent se) fires up on session expiration.
The HttpSessionEvent object allows access to the modified session through getSession().
ServletContextListener
This listener manages application lifecycle events. It notifies when the web application begins initialization (before filters and servlets) and when it shuts down (after all components have been destroyed).
The ServletContextEvent class offers getServletContext() for accessing the updated context.
Attribute Change Monitoring
HttpSessionAttributeListener
Monitors changes to session attributes including additions, removals, and replacements.
The HttpSessionBindingEvent object provides access to attribute name and value via getName() and getValue() methods.
ServletRequestAttributeListener
Tracks modifications to request attributes.
The ServletRequestAttributeEvent object exposes attribute details through similar methods.
ServletContextAttributeListener
Monitors changes to application-level attributes.
The ServletContextAttributeEvent class provides identical functionality for retrieving attribute information.
Session Object Monitoring
These two listeners differ from the others:
HttpSessionBindingListener
Objects implementing this interface receive notifications when they are bound to or unbound from a session. The valueBound(HttpSessionBindingEvent event) method is called when an object is added to a session, and valueUnbound(HttpSessionBindingEvent event) when removed.
HttpSessionActivationListener
When a session is serialized (passivated) during server shutdown and deserialized (activated) during restart, this interface handles those events. The sessionDidActivate(HttpSessionEvent se) method executes during activation, while sessionWillPassivate(HttpSessionEvent se) runs during passivation.
Practical Implementation
Class Setup
Folowing the HelloWorld example, create a Listener class in the existing package that implements all required interfaces. Additionally, develop a Person class that implements the session object monitoring interfaces.
Implementation Details
Person Class Implementation
package com.test.cyw;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionEvent;
public class Person implements HttpSessionActivationListener, HttpSessionBindingListener {
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private String name;
private int age;
@Override
public void valueBound(HttpSessionBindingEvent event) {
System.out.println("Bound to session - Name:" + event.getName() + " Value:" + event.getValue());
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
System.out.println("Unbound from session - Name:" + event.getName() + " Value:" + event.getValue());
}
@Override
public void sessionDidActivate(HttpSessionEvent event) {
System.out.println("Session activated");
}
@Override
public void sessionWillPassivate(HttpSessionEvent event) {
System.out.println("Session passivated");
}
}
Listener Implementation
package com.test.cyw;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener
public class MyListener implements ServletContextListener, HttpSessionListener, ServletRequestListener,
HttpSessionAttributeListener, ServletRequestAttributeListener, ServletContextAttributeListener {
public MyListener() {}
@Override
public void sessionCreated(HttpSessionEvent event) {
System.out.println("Session created");
}
@Override
public void requestDestroyed(ServletRequestEvent event) {
System.out.println("Request destroyed");
}
@Override
public void requestInitialized(ServletRequestEvent event) {
System.out.println("Request initialized");
}
@Override
public void sessionDestroyed(HttpSessionEvent event) {
System.out.println("Session destroyed");
}
@Override
public void contextDestroyed(ServletContextEvent event) {
System.out.println("Context destroyed - Parameter:" + event.getServletContext().getInitParameter("ImageType"));
}
@Override
public void contextInitialized(ServletContextEvent event) {
System.out.println("Context initialized - Parameter:" + event.getServletContext().getInitParameter("ImageType"));
}
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
System.out.println("Session attribute added - Name:" + event.getName() + " Value:" + event.getValue());
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
System.out.println("Session attribute removed - Name:" + event.getName() + " Value:" + event.getValue());
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
System.out.println("Session attribute replaced - Name:" + event.getName() + " Value:" + event.getValue());
}
@Override
public void attributeAdded(ServletRequestAttributeEvent event) {
System.out.println("Request attribute added - Name:" + event.getName() + " Value:" + event.getValue());
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent event) {
System.out.println("Request attribute removed - Name:" + event.getName() + " Value:" + event.getValue());
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent event) {
System.out.println("Request attribute replaced - Name:" + event.getName() + " Value:" + event.getValue());
}
@Override
public void attributeAdded(ServletContextAttributeEvent event) {
System.out.println("Context attribute added - Name:" + event.getName() + " Value:" + event.getValue());
}
@Override
public void attributeRemoved(ServletContextAttributeEvent event) {
System.out.println("Context attribute removed - Name:" + event.getName() + " Value:" + event.getValue());
}
@Override
public void attributeReplaced(ServletContextAttributeEvent event) {
System.out.println("Context attribute replaced - Name:" + event.getName() + " Value:" + event.getValue());
}
}
JSP Testing Page
<body>
<% Person person = new Person("CuiYW", 25); %>
<%
response.setCharacterEncoding("UTF-8");
request.setCharacterEncoding("UTF-8");
session.setAttribute("Person", person);
session.setAttribute("ID", "123456");
session.setAttribute("ID", "abcdef");
session.removeAttribute("ID");
%>
</body>
Configuration
While most listeners are automatically discovered, session object listeners require explicit configuration in web.xml. The standard listener configuration would appear as follows:
<listener>
<listener-class>com.test.cyw.MyListener</listener-class>
</listener>
Execution Results
Starting the Tomcat server and accessing the test.jsp page followed by shutting down the server produces console output showing all listener events being triggered appropriately.