ServletContextListener 서블릿 리스너 예제
ServletContextListener는 우리가 가지고 있는 많은 Servlet Listener 중 하나입니다. 이것은 Java Web Application 시리즈의 다섯 번째 기사입니다. 이전 네 개의 기사도 확인하고 싶을 수 있습니다.
- 자바 웹 애플리케이션
- 자바의 서블릿
- 서블릿 세션 관리
- 서블릿 필터
서블릿 리스너

서블릿 리스너가 있는 이유는 무엇입니까? 서블릿 리스너 인터페이스 및 이벤트 객체 서블릿 리스너 구성 서블릿 리스너 예 ServletContextListener ServletContextAttributeListener HttpSessionListener 서블릿 요청 리스너 서블릿 리스너가 있는 이유는 무엇입니까?
우리는 ServletContext
를 사용하여 다른 모든 서블릿이 액세스할 수 있는 애플리케이션 범위를 가진 속성을 생성할 수 있지만 배포 설명자(web.xml)에서만 문자열로 ServletContext 초기 매개변수를 초기화할 수 있음을 알고 있습니다. 애플리케이션이 데이터베이스 지향적이고 데이터베이스 연결을 위해 ServletContext에 속성을 설정하려는 경우 어떻게 됩니까? 애플리케이션에 단일 진입점(사용자 로그인)이 있는 경우 첫 번째 서블릿 요청에서 이를 수행할 수 있지만 진입점이 여러 개인 경우 모든 곳에서 이를 수행하면 많은 코드 중복이 발생합니다. 또한 데이터베이스가 다운되었거나 제대로 구성되지 않은 경우 첫 번째 클라이언트 요청이 서버에 올 때까지 알 수 없습니다. 이러한 시나리오를 처리하기 위해 서블릿 API는 이벤트를 수신하고 특정 작업을 수행하도록 구현 및 구성할 수 있는 수신기 인터페이스를 제공합니다. 이벤트는 무언가 발생하는 것입니다. 웹 애플리케이션 세계에서 이벤트는 애플리케이션의 초기화, 애플리케이션 파괴, 클라이언트의 요청, 세션 생성/파괴, 세션의 속성 수정 등이 될 수 있습니다. Servlet API는 우리가 구현할 수 있는 다양한 유형의 리스너 인터페이스를 제공합니다. 특정 이벤트가 발생할 때 무언가를 처리하도록 web.xml에서 구성합니다. 예를 들어, 위의 시나리오에서 우리는 애플리케이션 시작 이벤트에 대한 리스너를 생성하여 컨텍스트 초기화 매개변수를 읽고 데이터베이스 연결을 생성하고 다른 리소스에서 사용할 수 있도록 컨텍스트 속성으로 설정할 수 있습니다.8. ### 서블릿 리스너 인터페이스 및 이벤트 객체
Servlet API는 다양한 유형의 이벤트에 대해 다양한 종류의 리스너를 제공합니다. 리스너 인터페이스는 유사한 이벤트 그룹과 함께 작동하는 메서드를 선언합니다. 예를 들어 컨텍스트의 시작 및 종료 이벤트를 수신하는 ServletContext Listener가 있습니다. 리스너 인터페이스의 모든 메소드는 Event 객체를 입력으로 사용합니다. 이벤트 객체는 리스너에게 특정 객체를 제공하는 래퍼 역할을 합니다. Servlet API는 다음과 같은 이벤트 객체를 제공합니다.
- javax.servlet.AsyncEvent - ServletRequest에서 시작된 비동기 작업(ServletRequest#startAsync 또는 ServletRequest#startAsync(ServletRequest, ServletResponse)에 대한 호출을 통해)이 완료, 시간 초과 또는 오류 생성 시 발생하는 이벤트입니다.
- javax.servlet.http.HttpSessionBindingEvent - 이 유형의 이벤트는 세션에서 결합 또는 결합 해제될 때 HttpSessionBindingListener를 구현하는 객체로 전송되거나 속성이 있을 때 web.xml에 구성된 HttpSessionAttributeListener로 전송됩니다. 바인딩, 바인딩 해제 또는 세션에서 대체됩니다. 세션은 HttpSession.setAttribute를 호출하여 객체를 결합하고 HttpSession.removeAttribute를 호출하여 객체를 결합 해제합니다. 개체가 세션에서 제거될 때 정리 작업에 이 이벤트를 사용할 수 있습니다.
- javax.servlet.http.HttpSessionEvent - 웹 애플리케이션 내의 세션 변경에 대한 이벤트 알림을 나타내는 클래스입니다.
- javax.servlet.ServletContextAttributeEvent - 웹 애플리케이션의 ServletContext 속성 변경에 대한 알림을 위한 이벤트 클래스
- javax.servlet.ServletContextEvent - 웹 애플리케이션의 서블릿 컨텍스트 변경에 대한 알림을 위한 이벤트 클래스입니다.
- javax.servlet.ServletRequestEvent - 이러한 종류의 이벤트는 ServletRequest에 대한 수명 주기 이벤트를 나타냅니다. 이벤트 소스는 이 웹 애플리케이션의 ServletContext입니다.
- javax.servlet.ServletRequestAttributeEvent - 애플리케이션에서 서블릿 요청의 속성 변경 알림을 위한 이벤트 클래스입니다.
Servlet API는 다음과 같은 Listener 인터페이스를 제공합니다.
javax.servlet.AsyncListener - 리스너가 추가된 ServletRequest에서 시작된 비동기 작업이 완료, 시간 초과 또는 오류가 발생한 경우 알림을 받을 리스너입니다.\n\n\njavax.servlet.ServletContextListener - ServletContext 수명 주기 변경에 대한 알림 이벤트를 수신하기 위한 인터페이스입니다.\n\n\njavax.servlet.ServletContextAttributeListener - ServletContext 속성 변경에 대한 알림 이벤트를 수신하기 위한 인터페이스입니다.\n\n\njavax.servlet.ServletRequestListener - 웹 애플리케이션의 범위에 들어오고 나가는 요청에 대한 알림 이벤트를 수신하기 위한 인터페이스입니다.\n\n\njavax.servlet.ServletRequestAttributeListener - ServletRequest 속성 변경에 대한 알림 이벤트를 수신하기 위한 인터페이스입니다.\n\n\njavax.servlet.http.HttpSessionListener - HttpSession 수명 주기 변경에 대한 알림 이벤트를 수신하기 위한 인터페이스입니다.\n\n\njavax.servlet.http.HttpSessionBindingListener - 객체가 세션에 바인딩되거나 바인딩 해제될 때 알림을 받도록 합니다.\n\n\njavax.servlet.http.HttpSessionAttributeListener - HttpSession 속성 변경에 대한 알림 이벤트를 수신하기 위한 인터페이스입니다.\n\n\njavax.servlet.http.HttpSessionActivationListener - 세션에 바인딩된 개체는 세션이 비활성화되고 해당 세션이 활성화됨을 알리는 컨테이너 이벤트를 수신할 수 있습니다. HttpSessionActivationListener를 구현하는 세션에 바인딩된 모든 특성을 알리려면 VM 간에 세션을 마이그레이션하거나 세션을 유지하는 컨테이너가 필요합니다.\n\n\n서블릿 리스너 구성
주석을 사용하여 클래스를 Listener로 선언할 수 있지만 클래스는 하나 이상의 Listener 인터페이스를 구현해야 합니다. web.xml에서 리스너를 다음과 같이 정의할 수 있습니다.
<listener>
<listener-class>
com.journaldev.listener.AppContextListener
</listener-class>
</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: 이것은 데이터베이스 연결을 위한 클래스입니다. 단순화를 위해 실제 데이터베이스 연결을 위한 코드는 제공하지 않습니다. 이 객체를 서블릿 컨텍스트의 속성으로 설정합니다.
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;
//create db connection now
}
public Connection getConnection(){
return this.con;
}
public void closeConnection(){
//close DB connection here
}
}
MyServlet: 세션, 속성 등으로 작업할 간단한 서블릿 클래스입니다.
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);
}
}
이제 리스너 클래스를 구현할 것입니다. 일반적으로 사용되는 리스너인 ServletContextListener, ServletContextAttributeListener, ServletRequestListener 및 HttpSessionListener.27에 대한 샘플 리스너 클래스를 제공합니다. ## ServletContextListener
서블릿 컨텍스트 초기화 매개변수를 읽어 DBConnectionManager 객체를 생성하고 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");
//create database connection from init parameters and set it to context
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.");
}
}
ServletContextAttributeListener
서블릿 컨텍스트에서 속성이 추가, 제거 또는 대체될 때 이벤트를 기록하는 간단한 구현입니다.
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()+"}");
}
}
HttpSessionListener
세션이 생성되거나 소멸될 때 이벤트를 기록하는 간단한 구현입니다.
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());
}
}
서블릿 요청 리스너
요청이 초기화 및 소멸될 때 ServletRequest IP 주소를 기록하기 위한 ServletRequestListener 인터페이스의 간단한 구현입니다.
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());
}
}
이제 애플리케이션을 배포하고 URL https://localhost:8080/ServletListenerExample/MyServlet
을 사용하여 브라우저에서 MyServlet에 액세스하면 서버 로그 파일에 다음 로그가 표시됩니다.
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.
로그의 순서와 실행 순서를 확인하십시오. 애플리케이션을 종료하거나 컨테이너를 종료하면 마지막 로그가 나타납니다.
이것이 서블릿의 리스너에 대한 전부입니다. 다음으로 쿠키와 몇 가지 일반적인 서블릿 예제를 살펴보겠습니다. 아래 링크에서 프로젝트를 다운로드하고 가지고 놀면서 자세히 알아볼 수 있습니다.
서블릿 리스너 예제 프로젝트 다운로드
Servlet의 쿠키에 대한 시리즈의 다음 기사를 확인하십시오.