`ServletContextListener` 서블릿 리스너 예제

ServletContextListener 는 우리가 가지고 있는 많은 Servlet Listener 중 하나입니다. 이것은 Java Web Application 시리즈의 다섯 번째 기사입니다. 이전의 네 개의 기사도 확인해보시기 바랍니다.

  1. Java Web Application
  2. Java에서의 Servlets
  3. Servlet 세션 관리
  4. Servlet 필터

Servlet 리스너

이 튜토리얼에서는 서블릿 리스너, 서블릿 리스너의 장점, 리스너를 사용하여 수행할 수 있는 몇 가지 일반적인 작업, 서블릿 API 리스너 인터페이스 및 이벤트 객체에 대해 알아볼 것입니다. 마지막으로 ServletContext, 세션ServletRequest에 대한 일반적으로 사용되는 리스너 구현 예제를 보여주기 위해 간단한 웹 프로젝트를 만들 것입니다.

  1. 왜 서블릿 리스너가 필요한가요?

  2. 서블릿 리스너 인터페이스 및 이벤트 객체

  3. 서블릿 리스너 구성

  4. 서블릿 리스너 예제

  5. ServletContextListener

  6. ServletContextAttributeListener

  7. HttpSessionListener

  8. ServletRequestListener

  9. 왜 Servlet 리스너를 사용하나요?

우리는 ServletContext를 사용하여 모든 다른 서블릿이 접근할 수 있는 애플리케이션 범위의 속성을 만들 수 있다는 것을 알고 있습니다. 그러나 배포 설명자 (web.xml)에서는 ServletContext 초기화 매개변수를 문자열로만 초기화 할 수 있습니다. 그렇다면 우리의 애플리케이션은 데이터베이스 지향적이고 ServletContext에 데이터베이스 연결을 설정하려면 어떻게해야 할까요? 애플리케이션이 단일 진입점 (사용자 로그인)을 가지고 있다면 첫 번째 서블릿 요청에서 할 수 있지만, 여러 진입점이있는 경우 모든 곳에서 수행하면 많은 코드 중복이 발생합니다. 또한 데이터베이스가 다운되거나 제대로 구성되지 않은 경우 첫 번째 클라이언트 요청이 서버로 전달 될 때까지 알 수 없습니다. 이러한 시나리오를 처리하기 위해 서블릿 API는 이벤트를 수신하고 특정 작업을 수행할 수 있도록 구성 할 수있는 리스너 인터페이스를 제공합니다. 이벤트는 무언가의 발생을 의미하며, 웹 애플리케이션 세계에서 이벤트는 애플리케이션의 초기화, 애플리케이션의 소멸, 클라이언트의 요청, 세션의 생성/소멸, 세션에서의 속성 수정 등이 될 수 있습니다. Servlet API는 특정 이벤트가 발생했을 때 무언가를 처리하기 위해 구현하고 구성할 수있는 다양한 유형의 리스너 인터페이스를 제공합니다. 예를 들어, 위의 시나리오에서는 애플리케이션 시작 이벤트에 대한 리스너를 생성하여 context init 매개변수를 읽고 데이터베이스 연결을 생성하고 다른 리소스에서 사용할 수 있도록 context 속성에 설정할 수 있습니다. 8. ### Servlet 리스너 인터페이스 및 이벤트 객체

Servlet API는 다양한 종류의 이벤트에 대한 다른 종류의 리스너를 제공합니다. 리스너 인터페이스는 유사한 이벤트 그룹과 작업하기 위한 메소드를 선언합니다. 예를 들어, ServletContext 리스너는 컨텍스트의 시작 및 종료 이벤트를 수신하기 위해 사용됩니다. 리스너 인터페이스의 각 메소드는 이벤트 객체를 입력으로 받습니다. 이벤트 객체는 리스너에게 특정 객체를 제공하기 위한 래퍼 역할을 합니다. Servlet API는 다음과 같은 이벤트 객체를 제공합니다.

  1. javax.servlet.AsyncEvent – ServletRequest에서 비동기 작업(ServletRequest#startAsync 또는 ServletRequest#startAsync(ServletRequest, ServletResponse)를 통한 호출)이 완료되거나 시간 초과 또는 오류가 발생할 때 발생하는 이벤트입니다.
  2. javax.servlet.http.HttpSessionBindingEvent – 이 유형의 이벤트는 세션에 바인딩되거나 언바인딩 될 때 HttpSessionBindingListener를 구현하는 객체로 보내지거나, 웹.xml에 구성된 HttpSessionAttributeListener에 의해 세션에 어떤 속성이 바인딩되거나 언바인딩되거나 대체될 때 보내집니다. 세션은 HttpSession.setAttribute를 통해 객체를 바인딩하고 HttpSession.removeAttribute를 통해 객체를 언바인딩합니다. 이 이벤트를 사용하여 객체가 세션에서 제거될 때 정리 작업을 수행할 수 있습니다.
  3. javax.servlet.http.HttpSessionEvent – 이는 웹 애플리케이션 내에서 세션 변경 사항에 대한 이벤트 알림을 나타내는 클래스입니다.
  4. javax.servlet.ServletContextAttributeEvent – 웹 애플리케이션의 ServletContext 속성에 대한 변경 사항에 대한 알림을 위한 이벤트 클래스입니다.
  5. javax.servlet.ServletContextEvent – 이는 웹 애플리케이션의 서블릿 컨텍스트에 대한 변경 사항에 대한 알림을 위한 이벤트 클래스입니다.
  6. javax.servlet.ServletRequestEvent – 이러한 종류의 이벤트는 ServletRequest의 라이프사이클 이벤트를 나타냅니다. 이벤트의 소스는 이 웹 애플리케이션의 ServletContext입니다.
  7. javax.servlet.ServletRequestAttributeEvent – 이는 애플리케이션에서 서블릿 요청의 속성 변경에 대한 알림을 위한 이벤트 클래스입니다.

Servlet API는 다음과 같은 리스너 인터페이스를 제공합니다.

  1. javax.servlet.AsyncListener – 해당 리스너가 추가된 ServletRequest에서 비동기 작업이 완료되거나 시간 초과 또는 오류가 발생한 경우에 알림을 받는 리스너입니다.

  2. javax.servlet.ServletContextListener – ServletContext의 라이프사이클 변경에 대한 알림 이벤트를 수신하기 위한 인터페이스입니다.

  3. javax.servlet.ServletContextAttributeListener – ServletContext 속성 변경에 대한 알림 이벤트를 수신하기 위한 인터페이스입니다.

  4. javax.servlet.ServletRequestListener – 웹 애플리케이션의 요청이 범위에 들어오거나 범위를 벗어나는 것에 대한 알림 이벤트를 받기 위한 인터페이스입니다.

  5. javax.servlet.ServletRequestAttributeListener – ServletRequest 속성 변경에 대한 알림 이벤트를 받기 위한 인터페이스입니다.

  6. javax.servlet.http.HttpSessionListener – HttpSession 수명 주기 변경에 대한 알림 이벤트를 받기 위한 인터페이스입니다.

  7. javax.servlet.http.HttpSessionBindingListener – 객체가 세션에 바인딩되거나 언바인딩될 때 알림을 받기 위한 인터페이스입니다.

  8. javax.servlet.http.HttpSessionAttributeListener – HttpSession 속성 변경에 대한 알림 이벤트를 받기 위한 인터페이스입니다.

  9. javax.servlet.http.HttpSessionActivationListener – 세션에 바인딩된 객체는 세션이 비활성화되고 활성화될 것임을 알리는 컨테이너 이벤트를 수신할 수 있습니다. 세션을 VM 간에 이동하거나 세션을 영구 저장하는 컨테이너는 HttpSessionActivationListener를 구현한 모든 세션에 바인딩된 속성에 대해 알림을 보내야 합니다.

  10. Servlet 리스너 구성

우리는 클래스를 Listener로 선언하기 위해 @WebListener 주석을 사용할 수 있습니다. 그러나 클래스는 하나 이상의 Listener 인터페이스를 구현해야 합니다. 우리는 web.xml에서 리스너를 정의할 수 있습니다:

<listener>
    <listener-class>
    com.journaldev.listener.AppContextListener
    </listener-class>
</listener>
  1. Servlet Listener 예제

서블릿 리스너가 작동하는 것을 확인하기 위해 간단한 웹 애플리케이션을 만들어 보겠습니다. 우리는 Eclipse에서 동적 웹 프로젝트를 만들 것입니다. ServletListenerExample 이 프로젝트 구조는 아래 이미지와 같이 보일 것입니다. web.xml: 배치 서술자에서 일부 컨텍스트 초기 매개변수와 리스너 구성을 정의할 것입니다.

<?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;
		//지금 데이터베이스 연결 생성
		
	}
	
	public Connection getConnection(){
		return this.con;
	}
	
	public void closeConnection(){
		//여기서 데이터베이스 연결 닫기
	}
}

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");
    	
    	//초기 매개변수에서 데이터베이스 연결 생성하고 컨텍스트에 설정
    	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());
    }
	
}

이제 우리가 애플리케이션을 배포하고 브라우저에서 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.

로그의 순서에 주목하십시오. 마지막 로그는 애플리케이션을 종료하거나 컨테이너를 종료할 때 나타납니다.

서블릿의 리스너에 대한 설명은 여기까지입니다. 다음으로 쿠키와 일반적인 서블릿 예제에 대해 살펴보겠습니다. 아래 링크에서 프로젝트를 다운로드하여 더 많이 배울 수 있습니다.

서블릿 리스너 예제 프로젝트 다운로드

시리즈에서 다음 기사를 확인하세요. 서블릿에서의 쿠키에 대한 내용입니다.

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