O ServletContextListener é um dos muitos Ouvintes de Servlet que temos. Este é o quinto artigo da série de Aplicação Web Java, você pode querer conferir os quatro artigos anteriores também.
Ouvinte de Servlet
Neste tutorial, vamos analisar o listener de servlet, os benefícios dos listeners de servlet, algumas tarefas comuns que podemos fazer com listeners, interfaces de eventos de listeners de API de servlet e objetos de eventos. No final, criaremos um projeto web simples para mostrar um exemplo de implementação de Listener comumente usado para ServletContext, Session e ServletRequest.
Nós sabemos que usando ServletContext
, podemos criar um atributo com escopo de aplicação que todos os outros servlets podem acessar, mas podemos inicializar os parâmetros de inicialização do ServletContext apenas como String no descritor de implantação (web.xml). E se nossa aplicação for orientada a banco de dados e quisermos definir um atributo no ServletContext para a conexão com o banco de dados? Se sua aplicação tiver um único ponto de entrada (login do usuário), você pode fazer isso na primeira solicitação do servlet. Mas se tivermos vários pontos de entrada, fazer isso em todos os lugares resultará em muita redundância de código. Além disso, se o banco de dados estiver fora do ar ou não estiver configurado corretamente, não saberemos até que a primeira solicitação do cliente chegue ao servidor. Para lidar com esses cenários, a API de servlets fornece interfaces de Listener que podemos implementar e configurar para ouvir um evento e realizar determinadas operações. Evento é a ocorrência de algo, no mundo de aplicativos web, um evento pode ser a inicialização da aplicação, destruição de uma aplicação, solicitação do cliente, criação/destruição de uma sessão, modificação de atributo na sessão, etc. A API de Servlets fornece diferentes tipos de interfaces de Listener que podemos implementar e configurar no web.xml para processar algo quando ocorre um evento específico. Por exemplo, no cenário acima, podemos criar um Listener para o evento de inicialização da aplicação para ler os parâmetros de inicialização do contexto e criar uma conexão com o banco de dados, definindo-a como atributo de contexto para uso por outros recursos.8. ### Interfaces de Listener de Servlet e Objetos de Evento
A API Servlet fornece diferentes tipos de listeners para diferentes tipos de eventos. As interfaces de listener declaram métodos para trabalhar com grupos de eventos semelhantes. Por exemplo, temos o ServletContext Listener para ouvir eventos de inicialização e desligamento do contexto. Cada método na interface do listener recebe um objeto Event como entrada. O objeto Event funciona como um invólucro para fornecer um objeto específico aos ouvintes. A API Servlet fornece os seguintes objetos de evento.
- javax.servlet.AsyncEvent – Evento disparado quando a operação assíncrona iniciada em um ServletRequest (via uma chamada para ServletRequest#startAsync ou ServletRequest#startAsync(ServletRequest, ServletResponse)) é concluída, expirou ou gerou um erro.
- javax.servlet.http.HttpSessionBindingEvent – Eventos deste tipo são enviados para um objeto que implementa HttpSessionBindingListener quando ele é vinculado ou desvinculado de uma sessão, ou para um HttpSessionAttributeListener configurado no web.xml quando qualquer atributo é vinculado, desvinculado ou substituído em uma sessão. A sessão vincula o objeto por meio de uma chamada para HttpSession.setAttribute e desvincula o objeto por meio de uma chamada para HttpSession.removeAttribute. Podemos usar esse evento para atividades de limpeza quando o objeto é removido da sessão.
- javax.servlet.http.HttpSessionEvent – Esta é a classe que representa notificações de eventos para alterações em sessões dentro de uma aplicação web.
- javax.servlet.ServletContextAttributeEvent – Classe de evento para notificações sobre alterações nos atributos do ServletContext de uma aplicação web.
- javax.servlet.ServletContextEvent – Esta é a classe de evento para notificações sobre alterações no contexto do servlet de uma aplicação web.
- javax.servlet.ServletRequestEvent – Eventos deste tipo indicam eventos do ciclo de vida para um ServletRequest. A fonte do evento é o ServletContext desta aplicação web.
- javax.servlet.ServletRequestAttributeEvent – Esta é a classe de evento para notificações de alterações nos atributos da solicitação de servlet em uma aplicação.
A API do Servlet fornece as seguintes interfaces de Listener.
-
javax.servlet.AsyncListener – Listener que será notificado no caso de uma operação assíncrona iniciada em um ServletRequest ao qual o ouvinte foi adicionado ter sido concluída, expirado ou resultou em um erro.
-
javax.servlet.ServletContextListener – Interface para receber eventos de notificação sobre alterações no ciclo de vida do ServletContext.
-
javax.servlet.ServletContextAttributeListener – Interface para receber eventos de notificação sobre alterações nos atributos do ServletContext.
-
javax.servlet.ServletRequestListener – Interface para receber eventos de notificação sobre solicitações que entram e saem do escopo de uma aplicação web.
-
javax.servlet.ServletRequestAttributeListener – Interface para receber eventos de notificação sobre alterações de atributos do ServletRequest.
-
javax.servlet.http.HttpSessionListener – Interface para receber eventos de notificação sobre alterações no ciclo de vida do HttpSession.
-
javax.servlet.http.HttpSessionBindingListener – Faz com que um objeto seja notificado quando está vinculado a uma sessão ou desvinculado dela.
-
javax.servlet.http.HttpSessionAttributeListener – Interface para receber eventos de notificação sobre alterações de atributos do HttpSession.
-
javax.servlet.http.HttpSessionActivationListener – Objetos vinculados a uma sessão podem ouvir eventos do contêiner que os notificam de que as sessões serão passivadas e que a sessão será ativada. Um contêiner que migra sessões entre VMs ou persiste sessões deve notificar todos os atributos vinculados a sessões que implementam HttpSessionActivationListener.
-
Configuração do Ouvinte do Servlet
Podemos usar a @WebListener anotação para declarar uma classe como Listener, no entanto a classe deve implementar uma ou mais das interfaces Listener. Podemos definir um listener no web.xml como:
<listener>
<listener-class>
com.journaldev.listener.AppContextListener
</listener-class>
</listener>
Vamos criar uma aplicação web simples para ver o listener do servlet em ação. Vamos criar um projeto web dinâmico no Eclipse ServletListenerExample cuja estrutura do projeto será semelhante à imagem abaixo. web.xml: No descritor de implantação, vou definir alguns parâmetros de inicialização do contexto e configuração do 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 é a classe para conectividade com o banco de dados, para simplificar, não estou fornecendo código para a conexão real com o banco de dados. Vamos definir este objeto como atributo do contexto do 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;
// criar conexão com o banco de dados agora
}
public Connection getConnection(){
return this.con;
}
public void closeConnection(){
// fechar a conexão com o banco de dados aqui
}
}
MyServlet: Uma classe de servlet simples onde vou trabalhar com sessão, 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);
}
}
Agora vamos implementar classes de listener, estou fornecendo exemplos para listeners comumente usados – ServletContextListener, ServletContextAttributeListener, ServletRequestListener e HttpSessionListener.27. ## ServletContextListener
Vamos ler os parâmetros de inicialização do contexto do servlet para criar o objeto DBConnectionManager e definir isso como atributo do 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");
// criar conexão com o banco de dados a partir dos parâmetros de inicialização e definir no 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.");
}
}
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());
}
}
Agora, quando implantarmos nossa aplicação e acessarmos MyServlet no navegador com o URL https://localhost:8080/ServletListenerExample/MyServlet
, veremos os seguintes logs no arquivo de log do 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.
Observe a sequência de logs e está na ordem de execução. O último log aparecerá quando você desligar a aplicação ou desligar o contêiner.
Isso é tudo para o ouvinte no servlet, vamos analisar os cookies e alguns exemplos comuns de servlets em seguida. Você pode baixar o projeto no link abaixo e brincar com ele para aprender mais.
Baixar Projeto Exemplo do Servlet Listener
Confira o próximo artigo da série sobre Cookies em Servlet.
Source:
https://www.digitalocean.com/community/tutorials/servletcontextlistener-servlet-listener-example