Ejemplo de Servlet Listener ServletContextListener

El ServletContextListener es uno de los muchos Oyentes de Servlet que tenemos. Este es el quinto artículo en la serie de Java Web Application, es posible que desees consultar también los cuatro artículos anteriores.

  1. Java Web Application
  2. Servlets en Java
  3. Manejo de Sesiones en Servlet
  4. Filtro de Servlet

Oyente de Servlet

En este tutorial, veremos el listener de servlet, los beneficios de los listeners de servlet, algunas tareas comunes que podemos hacer con los listeners, las interfaces de listener de la API de servlet y los objetos de evento. Al final, crearemos un proyecto web simple para mostrar un ejemplo de implementación de Listener común para ServletContext, Session y ServletRequest.

  1. ¿Por qué tenemos un Listener de Servlet?

  2. Interfaces de Listener de Servlet y Objetos de Evento

  3. Configuración del Listener de Servlet

  4. Ejemplo de Listener de Servlet

  5. ServletContextListener

  6. ServletContextAttributeListener

  7. HttpSessionListener

  8. ServletRequestListener

  9. ¿Por qué tenemos Servlet Listener?

Conocemos que utilizando ServletContext, podemos crear un atributo con alcance de aplicación al que todos los demás servlets pueden acceder, pero podemos inicializar los parámetros de inicialización de ServletContext como String únicamente en el descriptor de implementación (web.xml). ¿Y si nuestra aplicación está orientada a la base de datos y queremos establecer un atributo en ServletContext para la conexión a la base de datos? Si nuestra aplicación tiene un único punto de entrada (inicio de sesión de usuario), entonces podemos hacerlo en la primera solicitud de servlet. Pero si tenemos múltiples puntos de entrada, hacerlo en todas partes resultará en mucha redundancia de código. Además, si la base de datos está caída o no está configurada correctamente, no lo sabremos hasta que llegue la primera solicitud del cliente al servidor. Para manejar estos escenarios, la API de servlet proporciona interfaces de escucha que podemos implementar y configurar para escuchar un evento y realizar ciertas operaciones. Un evento es la ocurrencia de algo, en el mundo de las aplicaciones web, un evento puede ser la inicialización de la aplicación, la destrucción de una aplicación, una solicitud del cliente, la creación/destrucción de una sesión, la modificación de un atributo en la sesión, etc. La API de Servlet proporciona diferentes tipos de interfaces de escucha que podemos implementar y configurar en el web.xml para procesar algo cuando ocurre un evento en particular. Por ejemplo, en el escenario anterior, podemos crear un escuchador para el evento de inicio de la aplicación que lea los parámetros de inicialización del contexto y cree una conexión a la base de datos y la establezca como un atributo de contexto para ser utilizada por otros recursos. 8. ### Interfaces de Escucha de Servlet y Objetos de Evento

La API Servlet proporciona diferentes tipos de listeners para diferentes tipos de eventos. Las interfaces de listener declaran métodos para trabajar con un grupo de eventos similares, por ejemplo, tenemos ServletContext Listener para escuchar el evento de inicio y apagado del contexto. Cada método en la interfaz del listener toma un objeto Event como entrada. El objeto Event funciona como un contenedor para proporcionar un objeto específico a los listeners. La API Servlet proporciona los siguientes objetos de evento.

  1. javax.servlet.AsyncEvent – Evento que se dispara cuando la operación asíncrona iniciada en un ServletRequest (a través de una llamada a ServletRequest#startAsync o ServletRequest#startAsync(ServletRequest, ServletResponse)) ha completado, expirado o producido un error.
  2. javax.servlet.http.HttpSessionBindingEvent – Los eventos de este tipo se envían a un objeto que implementa HttpSessionBindingListener cuando se vincula o desvincula de una sesión, o a un HttpSessionAttributeListener que ha sido configurado en el web.xml cuando se vincula, desvincula o reemplaza un atributo en una sesión. La sesión vincula el objeto mediante una llamada a HttpSession.setAttribute y desvincula el objeto mediante una llamada a HttpSession.removeAttribute. Podemos usar este evento para actividades de limpieza cuando se elimina el objeto de la sesión.
  3. javax.servlet.http.HttpSessionEvent – Esta es la clase que representa notificaciones de eventos para cambios en sesiones dentro de una aplicación web.
  4. javax.servlet.ServletContextAttributeEvent – Clase de evento para notificaciones sobre cambios en los atributos del ServletContext de una aplicación web.
  5. javax.servlet.ServletContextEvent – Esta es la clase de evento para notificaciones sobre cambios en el contexto del servlet de una aplicación web.
  6. javax.servlet.ServletRequestEvent – Los eventos de este tipo indican eventos del ciclo de vida para un ServletRequest. La fuente del evento es el ServletContext de esta aplicación web.
  7. javax.servlet.ServletRequestAttributeEvent – Esta es la clase de evento para notificaciones de cambios en los atributos de la solicitud de servlet en una aplicación.

La API de Servlet proporciona las siguientes interfaces de Listener.

  1. javax.servlet.AsyncListener – Listener que será notificado en caso de que una operación asíncrona iniciada en un ServletRequest al que se le haya agregado el listener haya sido completada, haya expirado o haya resultado en un error.

  2. javax.servlet.ServletContextListener – Interfaz para recibir eventos de notificación sobre cambios en el ciclo de vida del ServletContext.

  3. javax.servlet.ServletContextAttributeListener – Interfaz para recibir eventos de notificación sobre cambios en los atributos de ServletContext.

  4. javax.servlet.ServletRequestListener – Interfaz para recibir eventos de notificación sobre las solicitudes que entran y salen del ámbito de una aplicación web.

  5. javax.servlet.ServletRequestAttributeListener – Interfaz para recibir eventos de notificación sobre cambios en los atributos de ServletRequest.

  6. javax.servlet.http.HttpSessionListener – Interfaz para recibir eventos de notificación sobre cambios en el ciclo de vida de HttpSession.

  7. javax.servlet.http.HttpSessionBindingListener – Hace que un objeto sea notificado cuando se vincula o desvincula de una sesión.

  8. javax.servlet.http.HttpSessionAttributeListener – Interfaz para recibir eventos de notificación sobre cambios en los atributos de HttpSession.

  9. javax.servlet.http.HttpSessionActivationListener – Los objetos que están vinculados a una sesión pueden escuchar eventos del contenedor que les notifican que las sesiones serán pasivadas y que la sesión será activada. Se requiere que un contenedor que migra sesiones entre máquinas virtuales o persiste sesiones notifique a todos los atributos vinculados a sesiones que implementan HttpSessionActivationListener.

  10. Configuración del Oyente del Servlet

Podemos usar la @WebListener anotación para declarar una clase como Listener, sin embargo, la clase debe implementar una o más de las interfaces de Listener. Podemos definir un listener en web.xml como:

<listener>
    <listener-class>
    com.journaldev.listener.AppContextListener
    </listener-class>
</listener>
  1. Ejemplo de Servlet Listener

Creemos una aplicación web simple para ver el listener de servlet en acción. Crearemos un proyecto web dinámico en Eclipse ServletListenerExample cuya estructura del proyecto se verá como en la siguiente imagen. web.xml: En el descriptor de implementación, definiré algunos parámetros de inicialización de contexto y configuración del listener.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>ServletListenerExample</display-name>
  
  <context-param>
    <param-name>DBUSER</param-name>
    <param-value>pankaj</param-value>
  </context-param>
  <context-param>
    <param-name>DBPWD</param-name>
    <param-value>password</param-value>
  </context-param>
  <context-param>
    <param-name>DBURL</param-name>
    <param-value>jdbc:mysql://localhost/mysql_db</param-value>
  </context-param>
  
  <listener>
    <listener-class>com.journaldev.listener.AppContextListener</listener-class>
  </listener>
  <listener>
    <listener-class>com.journaldev.listener.AppContextAttributeListener</listener-class>
  </listener>
  <listener>
    <listener-class>com.journaldev.listener.MySessionListener</listener-class>
  </listener>
  <listener>
    <listener-class>com.journaldev.listener.MyServletRequestListener</listener-class>
  </listener>
</web-app>

DBConnectionManager: Esta es la clase para la conectividad con la base de datos, para simplificar no estoy proporcionando código para la conexión real a la base de datos. Configuraremos este objeto como atributo del contexto del servlet.

package com.journaldev.db;

import java.sql.Connection;

public class DBConnectionManager {

	private String dbURL;
	private String user;
	private String password;
	private Connection con;
	
	public DBConnectionManager(String url, String u, String p){
		this.dbURL=url;
		this.user=u;
		this.password=p;
		//crear conexión a la base de datos ahora
		
	}
	
	public Connection getConnection(){
		return this.con;
	}
	
	public void closeConnection(){
		//cerrar conexión a la base de datos aquí
	}
}

MyServlet: Una clase de servlet simple donde trabajaré con sesiones, atributos, etc.

package com.journaldev.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@WebServlet("/MyServlet")
public class MyServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
			ServletContext ctx = request.getServletContext();
			ctx.setAttribute("User", "Pankaj");
			String user = (String) ctx.getAttribute("User");
			ctx.removeAttribute("User");
			
			HttpSession session = request.getSession();
			session.invalidate();
			
			PrintWriter out = response.getWriter();
			out.write("Hi "+user);
	}

}

Ahora implementaremos clases de escucha. Estoy proporcionando clases de escucha de muestra para los escuchadores comúnmente utilizados: ServletContextListener, ServletContextAttributeListener, ServletRequestListener y HttpSessionListener.27. ## ServletContextListener

Leeremos los parámetros de inicialización del contexto del servlet para crear el objeto DBConnectionManager y establecerlo como atributo del objeto ServletContext.

package com.journaldev.listener;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

import com.journaldev.db.DBConnectionManager;

@WebListener
public class AppContextListener implements ServletContextListener {

    public void contextInitialized(ServletContextEvent servletContextEvent) {
    	ServletContext ctx = servletContextEvent.getServletContext();
    	
    	String url = ctx.getInitParameter("DBURL");
    	String u = ctx.getInitParameter("DBUSER");
    	String p = ctx.getInitParameter("DBPWD");
    	
    	//crear conexión a la base de datos a partir de los parámetros de inicialización y establecerlo en el contexto
    	DBConnectionManager dbManager = new DBConnectionManager(url, u, p);
    	ctx.setAttribute("DBManager", dbManager);
    	System.out.println("Database connection initialized for Application.");
    }

    public void contextDestroyed(ServletContextEvent servletContextEvent) {
    	ServletContext ctx = servletContextEvent.getServletContext();
    	DBConnectionManager dbManager = (DBConnectionManager) ctx.getAttribute("DBManager");
    	dbManager.closeConnection();
    	System.out.println("Database connection closed for Application.");
    	
    }
	
}
  1. ServletContextAttributeListener

A simple implementation to log the event when attribute is added, removed or replaced in servlet context.

package com.journaldev.listener;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class AppContextAttributeListener implements ServletContextAttributeListener {

    public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
    	System.out.println("ServletContext attribute added::{"+servletContextAttributeEvent.getName()+","+servletContextAttributeEvent.getValue()+"}");
    }

    public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
    	System.out.println("ServletContext attribute replaced::{"+servletContextAttributeEvent.getName()+","+servletContextAttributeEvent.getValue()+"}");
    }

    public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
    	System.out.println("ServletContext attribute removed::{"+servletContextAttributeEvent.getName()+","+servletContextAttributeEvent.getValue()+"}");
    }
	
}
  1. HttpSessionListener

A simple implementation to log the event when session is created or destroyed.

package com.journaldev.listener;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

@WebListener
public class MySessionListener implements HttpSessionListener {

    public void sessionCreated(HttpSessionEvent sessionEvent) {
    	System.out.println("Session Created:: ID="+sessionEvent.getSession().getId());
    }

    public void sessionDestroyed(HttpSessionEvent sessionEvent) {
    	System.out.println("Session Destroyed:: ID="+sessionEvent.getSession().getId());
    }
	
}
  1. ServletRequestListener

A simple implementation of ServletRequestListener interface to log the ServletRequest IP address when request is initialized and destroyed.

package com.journaldev.listener;

import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class MyServletRequestListener implements ServletRequestListener {

    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
    	ServletRequest servletRequest = servletRequestEvent.getServletRequest();
    	System.out.println("ServletRequest destroyed. Remote IP="+servletRequest.getRemoteAddr());
    }

    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
    	ServletRequest servletRequest = servletRequestEvent.getServletRequest();
    	System.out.println("ServletRequest initialized. Remote IP="+servletRequest.getRemoteAddr());
    }
	
}

Ahora, cuando despleguemos nuestra aplicación y accedamos a MyServlet en el navegador con la URL https://localhost:8080/ServletListenerExample/MyServlet, veremos los siguientes registros en el archivo de registro del servidor.

ServletContext attribute added::{DBManager,com.journaldev.db.DBConnectionManager@4def3d1b}
Database connection initialized for Application.
ServletContext attribute added::{org.apache.jasper.compiler.TldLocationsCache,org.apache.jasper.compiler.TldLocationsCache@1594df96}

ServletRequest initialized. Remote IP=0:0:0:0:0:0:0:1%0
ServletContext attribute added::{User,Pankaj}
ServletContext attribute removed::{User,Pankaj}
Session Created:: ID=8805E7AE4CCCF98AFD60142A6B300CD6
Session Destroyed:: ID=8805E7AE4CCCF98AFD60142A6B300CD6
ServletRequest destroyed. Remote IP=0:0:0:0:0:0:0:1%0


ServletRequest initialized. Remote IP=0:0:0:0:0:0:0:1%0
ServletContext attribute added::{User,Pankaj}
ServletContext attribute removed::{User,Pankaj}
Session Created:: ID=88A7A1388AB96F611840886012A4475F
Session Destroyed:: ID=88A7A1388AB96F611840886012A4475F
ServletRequest destroyed. Remote IP=0:0:0:0:0:0:0:1%0


Database connection closed for Application.

Observa la secuencia de registros y está en el orden de ejecución. El último registro aparecerá cuando cierres la aplicación o apagues el contenedor.

Eso es todo para el escucha en el servlet, a continuación veremos cookies y algunos ejemplos comunes de servlet. Puedes descargar el proyecto desde el siguiente enlace y jugar con él para aprender más.

Descargar Ejemplo de Proyecto de Oyente Servlet

Consulta el próximo artículo de la serie sobre Cookies en Servlet.

Source:
https://www.digitalocean.com/community/tutorials/servletcontextlistener-servlet-listener-example