Il `ServletContextListener` è uno dei molti `Servlet Listener` che abbiamo. Questo è il quinto articolo della serie su Java Web Application; potresti voler dare un’occhiata anche ai primi quattro articoli.
Servlet Listener
In questo tutorial, esamineremo il listener del servlet, i vantaggi dei listener del servlet, alcune attività comuni che possiamo svolgere con i listener, le interfacce degli eventi del listener dell’API del servlet. Alla fine creeremo un semplice progetto web per mostrare un esempio di implementazione di listener comunemente utilizzati per ServletContext, Sessione e ServletRequest.
Sappiamo che utilizzando ServletContext
, possiamo creare un attributo con ambito dell’applicazione a cui tutti gli altri servlet possono accedere, ma possiamo inizializzare solo i parametri di inizializzazione ServletContext come Stringa nel descrittore di distribuzione (web.xml). Se la nostra applicazione è orientata al database e vogliamo impostare un attributo in ServletContext per la connessione al database, possiamo farlo nella prima richiesta del servlet se l’applicazione ha un singolo punto di ingresso (accesso dell’utente). Tuttavia, se abbiamo più punti di ingresso, farlo ovunque comporterà molta ridondanza di codice. Inoltre, se il database non è disponibile o non è configurato correttamente, non lo sapremo fino a quando non arriverà la prima richiesta del client al server. Per gestire questi scenari, l’API servlet fornisce interfacce di ascolto che possiamo implementare e configurare per ascoltare un evento e eseguire determinate operazioni. Evento è l’occorrenza di qualcosa, nel mondo delle applicazioni web un evento può essere l’inizializzazione dell’applicazione, la distruzione di un’applicazione, la richiesta da parte del client, la creazione/distruzione di una sessione, la modifica di un attributo in una sessione, ecc. Servlet API fornisce diverse tipologie di interfacce di ascolto che possiamo implementare e configurare in web.xml per elaborare qualcosa quando si verifica un particolare evento. Ad esempio, nello scenario sopra descritto, possiamo creare un listener per l’evento di avvio dell’applicazione per leggere i parametri di inizializzazione del contesto e creare una connessione al database impostandola come attributo del contesto per l’uso da parte di altre risorse.
- javax.servlet.AsyncEvent – Evento che si attiva quando l’operazione asincrona avviata su una ServletRequest (tramite una chiamata a ServletRequest#startAsync o ServletRequest#startAsync(ServletRequest, ServletResponse)) è stata completata, ha temporaneamente superato il timeout o ha prodotto un errore.
- javax.servlet.http.HttpSessionBindingEvent – Gli eventi di questo tipo vengono inviati a un oggetto che implementa HttpSessionBindingListener quando viene associato o dissociato da una sessione, o a un HttpSessionAttributeListener configurato nel web.xml quando un attributo viene associato, dissociato o sostituito in una sessione. La sessione associa l’oggetto tramite una chiamata a HttpSession.setAttribute e lo dissocia tramite una chiamata a HttpSession.removeAttribute. Possiamo utilizzare questo evento per attività di pulizia quando l’oggetto viene rimosso dalla sessione.
- javax.servlet.http.HttpSessionEvent – Questa è la classe che rappresenta le notifiche degli eventi per le modifiche alle sessioni all’interno di un’applicazione web.
- javax.servlet.ServletContextAttributeEvent – Classe di evento per le notifiche sulle modifiche agli attributi del ServletContext di un’applicazione web.
- javax.servlet.ServletContextEvent – Questa è la classe degli eventi per le notifiche riguardanti le modifiche al contesto del servlet di un’applicazione web.
- javax.servlet.ServletRequestEvent – Gli eventi di questo tipo indicano eventi del ciclo di vita per un ServletRequest. La sorgente dell’evento è il ServletContext di questa applicazione web.
- javax.servlet.ServletRequestAttributeEvent – Questa è la classe degli eventi per le notifiche di modifiche agli attributi della richiesta servlet in un’applicazione.
L’API del servlet fornisce le seguenti interfacce di listener.
-
javax.servlet.AsyncListener – Listener che verrà notificato nel caso in cui un’operazione asincrona avviata su un ServletRequest a cui è stato aggiunto il listener sia completata, scaduta o abbia generato un errore.
-
javax.servlet.ServletContextListener – Interfaccia per ricevere eventi di notifica sulle modifiche al ciclo di vita di ServletContext.
-
javax.servlet.ServletContextAttributeListener – Interfaccia per ricevere eventi di notifica sulle modifiche agli attributi di ServletContext.
-
javax.servlet.ServletRequestListener – Interfaccia per ricevere eventi di notifica sugli accessi e sulle uscite delle richieste dal contesto di un’applicazione web.
-
javax.servlet.ServletRequestAttributeListener – Interfaccia per ricevere eventi di notifica sulle modifiche degli attributi di ServletRequest.
-
javax.servlet.http.HttpSessionListener – Interfaccia per ricevere eventi di notifica sulle modifiche del ciclo di vita di HttpSession.
-
javax.servlet.http.HttpSessionBindingListener – Fa sì che un oggetto venga notificato quando viene vincolato o scollegato da una sessione.
-
javax.servlet.http.HttpSessionAttributeListener – Interfaccia per ricevere eventi di notifica sulle modifiche degli attributi di HttpSession.
-
javax.servlet.http.HttpSessionActivationListener – Gli oggetti legati a una sessione possono ascoltare gli eventi del contenitore che notificano loro che le sessioni verranno attivate e che la sessione verrà attivata. Un contenitore che migra sessioni tra macchine virtuali o persiste sessioni è tenuto a notificare tutti gli attributi legati alle sessioni che implementano HttpSessionActivationListener.
-
Configurazione del Listener del Servlet
Possiamo utilizzare l’annotazione @WebListener per dichiarare una classe come Listener, tuttavia la classe dovrebbe implementare una o più delle interfacce Listener. Possiamo definire il listener in web.xml come segue:
<listener>
<listener-class>
com.journaldev.listener.AppContextListener
</listener-class>
</listener>
Creiamo un’applicazione web semplice per vedere il listener servlet in azione. Creeremo un progetto web dinamico in Eclipse ServletListenerExample che avrà una struttura di progetto simile all’immagine sottostante. web.xml: Nel descrittore di distribuzione, definirò alcuni parametri di inizializzazione del contesto e la configurazione 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: Questa è la classe per la connettività al database, per semplicità non fornisco il codice per la connessione effettiva al database. Imposteremo questo oggetto come attributo del contesto 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;
//creare connessione al database ora
}
public Connection getConnection(){
return this.con;
}
public void closeConnection(){
//chiudere la connessione al database qui
}
}
MyServlet: Una semplice classe servlet dove lavorerò con sessioni, attributi, ecc.
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);
}
}
Ora implementeremo classi di ascolto, sto fornendo esempi di classi di ascolto per gli ascoltatori comunemente usati: ServletContextListener, ServletContextAttributeListener, ServletRequestListener e HttpSessionListener.
## ServletContextListener
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");
Leggeremo i parametri di inizializzazione del contesto del servlet per creare l'oggetto DBConnectionManager e impostarlo come attributo dell'oggetto ServletContext.
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.");
}
}
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()+"}");
}
}
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());
}
}
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());
}
}
Ora, quando distribuiremo la nostra applicazione e accederemo a MyServlet nel browser con l’URL https://localhost:8080/ServletListenerExample/MyServlet
, vedremo i seguenti log nel file di registro del server.
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.
Nota la sequenza dei log e che è nell’ordine di esecuzione. L’ultimo log apparirà quando si arresterà l’applicazione o si arresterà il contenitore.
Questo è tutto per il listener nel servlet, esamineremo i cookie e alcuni esempi comuni di servlet dopo. Puoi scaricare il progetto dal link sottostante e sperimentare con esso per saperne di più.
Scarica il progetto di esempio del listener Servlet
Consulta l’articolo successivo della serie su I Cookies in Servlet.
Source:
https://www.digitalocean.com/community/tutorials/servletcontextlistener-servlet-listener-example