1. 리스너의 개념과 용도

  • 옵저버 패턴: 특정한 변화를 구독(subscribe)하는 객체들을 보관하고 있다가 변화가 발생(public)하면 구독 객체들을 실행
  • Servlet API는 여러 이벤트(Event)에 맞는 리스너들을 인터페이스로 정의해두었고 이를 통해 다음 작업 가능
    • 해당 웹 애플리케이션이 시작되거나 종료될 때 특정 작업 수행
    • HttpSession에 특정 작업에 대한 감시와 처리
    • HttpServletRequest에 특정 작업에 대한 감시와 처리

 


실습

 1) ServletContextListener

  - 해당 프로젝트가 실행되자 마자 실행시키고 싶은 작업

  - 프로젝트 내에 listener 패키지 생성 > 패키지 내에 W2AppListener 클래스 생성

// W2AppListener
package org.zerock.w2.listener;

import lombok.extern.log4j.Log4j2;

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

@WebListener
@Log4j2
public class W2AppListener implements ServletContextListener {
  
  // 시작할 때
  @Override
  public void contextInitialized(ServletContextEvent sce) {
    log.info("-----------------init-----------------");
    log.info("-----------------init-----------------");
    log.info("-----------------init-----------------");
  }
  
  // 끝낼 때
  @Override
  public void contextDestroyed(ServletContextEvent sce) {
    log.info("----------------destroy----------------");
    log.info("----------------destroy----------------");
    log.info("----------------destroy----------------");
  }
}

시작할 때 메세지 출력
끝낼 때 메세지 출력


 

 

  • ServletContextEvent와 ServletContext
    • contextInitialized()와 contextDestroyed()에는 파라미터로 ServletContextEvent라는 객체가 전달됨
    • ServletContextEvent를 이용하면 현재 애플리케이션이 실행되는 공간인 ServletContext에 접근 가능
    • ServletContext는 현재 웹 애플레케이션 내 모든 자원들을 같이 사용하는 공간
    • 이 공간에 무언가를 저장하면 모든 Controller나 JSP 등에서 이를 활용 가능
    • ServletContext에는 setAttribute()를 이용해서 원하는 이름으로 객체를 보관할 수 있음
    • 다음과 같이 'appName'이라는 이름으로 'W2'라는 이름을 지정하면, EL에서 ${appName}으로 이를 이용 가능

// W2AppListener에서 setAttribute()를 통해 객체를 생성
package org.zerock.w2.listener;

import lombok.extern.log4j.Log4j2;

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

@WebListener
@Log4j2
public class W2AppListener implements ServletContextListener {

  @Override
  public void contextInitialized(ServletContextEvent sce) {
    log.info("-----------------init-----------------");
    log.info("-----------------init-----------------");
    log.info("-----------------init-----------------");

    // 시작과 함께 객체 생성
    ServletContext servletContext = sce.getServletContext();
    servletContext.setAttribute("appName", "W2");
  }

  ...
  
}
// TodoListController에서 다음과 같이 객체 활용 가능
package org.zerock.w2.controller;

...

@WebServlet(name = "todoListController", value = "/todo/list")
@Log4j2
public class TodoListController extends HttpServlet {
  private TodoService todoService = TodoService.INSTANCE;

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    log.info("todo list.................");

    // getServletContext() 메서드를 이용해 ServletContext를 이용할 수 있음
    ServletContext servletContext = req.getServletContext();
    log.info("appName: " + servletContext.getAttribute("appName"));
    
    ...
    
  }
}
<!-- list.jsp에 다음과 같이 EL 구문을 추가하면 화면에서 나타내는 용도로 사용가능 -->
<body>
<h1>Todo List</h1>
<!-- appName이라는 이름을 가진 객체(W2)를 호출 -->
<h2>${appName}</h2>
<h2>${loginInfo}</h2>
<h3>${loginInfo.mname}</h3>

...

</body>

${appName}을 입력하여, appName을 이름으로 하는 객체 "W2"를 출력

 

  • ServletContextListener와 스프링 프레임워크
    • ServletContextListener와 ServletContext를 이용하면 프로젝트 실행 시 필요한 객체들을 준비하는 작업 처리 가능
    • 커넥션 풀 초기화 또는 TodoService 같은 객체 미리 생성해서 보관 등
    • 특히, 스프링 프레임워크에서 웹 프로젝트를 미리 로딩하는 작업을 처리할 때 ServletContextListener 이용

 


실습

 2) 세션 관리 리스너

  - Servlet의 리스너 중 HttpSession 관련 작업을 감시하는 리스너 등록 가능

              (HttpSessionListener나 HttpSessionAttributeListener 등)

  - 이를 이용해서 HttpSession이 생성되거나 setAttribute() 등의 작업이 이루어질 때를 감지 가능

  - listener 패키지에 LoginListener 클래스 추가

// LoginListener
package org.zerock.w2.listener;

import lombok.extern.log4j.Log4j2;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

@WebListener
@Log4j2
public class LoginListener implements HttpSessionAttributeListener {

  @Override
  public void attributeAdded(HttpSessionBindingEvent event) {
    // 이름과 객체의 값들을 받아옴
    String name = event.getName();
    Object obj = event.getValue();

    if(name.equals("loginIndo")) {
      log.info("A user logined.........");
      log.info(obj);
    }
  }
}

로그인 실행 시 로그에 위의 메세지가 출력됨

  - LoginListener는 HttpSessionAttributeListener 인터페이스를 구현

  - HttpSessionAttributeListener 인터페이스는 attributeAdded(), attributeRemoved(), attributeReplaced() 를 이용해서, HttpSession에 setAttribute() / removeAttribute() 등의 작업을 감지

+ Recent posts