Java - 18. Listener

들어가기 전

서블릿 관련 객체

1. HttpServletRequest

  • response전 담아둘 따근따근한 잠깐 존재할 정보

2. HttpServletResponse

3. HttpSession

  • session에 저장하면 session id로 구분하여 저장할 수 있음
  • 만약 얘를 ServletContext에 저장하게되면 그 정보를 서블릿 전체에서 공유하기때문에 session id로 구별짓는 의미가 없다.

4. ServletContext

  • Application scope를 관장하는 객체
  • WAS 관련 정보
    • ex) servletcontext.getServerInfo()

리스너

  • 객체마다 관련 이벤트가 일어날 때마다 통보받고 싶을 때 사용
  • 리스너의 특정 메서드를 톰캣이 호출해준다
  • 사용 예시
    • 1) 이벤트에 따라 해줘야하는 작업이 있다고 가정하자.
    • 2) 이벤트를 등록해서 호출되는 그 메서드에 원하는 작업을 기술해 준다.
    • 3) 실행시 톰캣이 알아서 호출 후 작업을 수행한다.
    • ex) 세션에 새로운 값 등록됨 (예: 사용자이름) -> 사용자이름 add되는 시점에 db에 insert하는 구문 작성
  • 약간 db 트리거와 비슷함
  • 필터와는 다름

Servlet Context Events

  • initilized에서 많이 쓰일듯
    • 그 시점에 프로그램내에서 같이 써야하는 변수나 내용이 있다면 initilized부분에 같이 초기화해주면 됨
    • ex) db connection 초기화
    • ex) 클라이언트쪽의 화면 (jsp, html..) 정의할때 url 경로에 context root같이 써줘야할때 root와 같은 구문들을 초기화하는데 쓸 수 있음
      • String url 말씀하시는듯함.. ㅠ

예제

MyServletContextListener.java

public class MyServletContextListener
	implements ServletContextListenr, ServletContextAttributeListener{
    
  /**
   * 서블릿 컨텍스트 객체가 제거 되었을 때 호출됨.
   * @param sce
   */
  @Override
  public void contextDestroyed(ServletContextEvent sce) {
      System.out.println("MyServletContextListener : contextDestroyed() 호출됨.");
  }

  /**
   * 서블릿 컨텍스트 객체가 초기화 되었을 때 호출됨.
   * @param sce
   */
  @Override
  public void contextInitialized(ServletContextEvent sce) {
      System.out.println("MyServletContextListener : contextInitialized() 호출됨.");
  }

  /**
   * 서블릿 컨텍스트에 속성값이 추가되었을 때
   * @param sce
   */
  @Override
  public void attributeAdded(ServletContextAttributeEvent scae) {
      System.out.println("MyServletContextListener : attributeAdded() 호출됨. => " + scae.getName());
  }

  /**
   * 서블릿 컨텍스트에 속성값이 삭제되었을 때
   * @param sce
   */
  @Override
  public void attributeRemoved(ServletContextAttributeEvent scae) {
      System.out.println("MyServletContextListener : attributeRemoved() 호출됨. => " + scae.getName());
  }

  /**
   * 서블릿 컨텍스트에 속성값이 변경(대체)되었을 때
   * @param sce
   */
  @Override
  public void attributeReplaced(ServletContextAttributeEvent scae) {
      System.out.println("MyServletContextListener : attributeReplaced() 호출됨. => " + scae.getName());
  }

}

web.xml

  • 필터, 에러, 서블릿과 달리 속성이 1줄임
<listener>
  <listener-class>kr.or.ddit.listener.MyServletContextListener</listener-class>
</listener>

T08_ServletContextListenerTest.java

  • 서블릿3.0부터 가능한 어노테이션 사용
  • 리스너도 서블릿의 일종
@WebServlet("/ServletContextListenerTest")
public class T08_ServletContextListenerTest extends HttpServlet {

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    // 속성값 추가
    req.getServletContext().setAttribute("ATTR1", "속성1");
    // 속성값 변경
    req.getServletContext().setAttribute("ATTR1", "속성1-1");
    // 속성값 추가
    req.getServletContext().setAttribute("ATTR2", "속성2");
    // 속성값 제거
    getServletContext().removeAttribute("ATTR1"); 
    // 이 클래스도 HttpServlet을 상속받고 있기 때문에 직접 getServletContext()할 수 있다.
  }

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    doGet(req, resp);
  }

}

결과

  • initialized ~ attribute ~ destroyed

Servlet Request Events

예제

  • 순서
    • 1) MyServletRequestListener.java 리스너 생성
    • 2) web.xml에 리스너 등록
    • 3) T09_ServletRequestListenerTest.java 테스트 파일 생성 및 어노테이션 등록

결과

  • initialized ~ attribute ~ destroyed

Http Session Events

예제

MySessionAttributeListener.java

  • Create Listener만들었더니 xml주석 날라가고 인덴트 난리남;;
    • ctrl+z해서 살리긴 했음..!
  • 속성 변화 이벤트를 감지하는 리스너
public class MySessionAttributeListener
	implements HttpSessionAttributeListener {

  public void attributeAdded(HttpSessionBindingEvent hsbe) {
    System.out.println("MySessionAttributeListener : attributeAdded() 호출됨. => Name : " + hsbe.getName() + ", Value : " + hsbe.getValue());
  }

  public void attributeRemoved(HttpSessionBindingEvent hsbe)  { 
    System.out.println("MySessionAttributeListener : attributeRemoved() 호출됨. => Name : " + hsbe.getName() + ", Value : " + hsbe.getValue());
  }

  public void attributeReplaced(HttpSessionBindingEvent hsbe)  { 
    System.out.println("MySessionAttributeListener : attributeReplaced() 호출됨. => Name : " + hsbe.getName() + ", Value : " + hsbe.getValue());
  }
}

web.xml

<listener>
  <listener-class>kr.or.ddit.listener.MySessionAttributeListener</listener-class>
</listener>

지금까지는 원래 있던 객체에 이벤트 처리


내가 만든 객체에 이벤트 처리

MySessionBindingListener.java

  • 기존방식: 리스너 만든 후 web.xml에 등록
  • 내가 관심있는 객체 내에 인터페이스를 구현해주면 그 객체의 행동을 모니터링함
  • 사용 예
    • MemberVO객체가 세션에 등록되는 순간을 알고시포요
  • https://dololak.tistory.com/713
public class MySessionBindingListener
	implements HttpSessionBindingListener {

  /**
   * HTTP 세션 영역 내에서 HttpSessionBindingListener를 구현한 객체가 바인딩 되면 호출됨
   */
  @Override
  public void valueBound(HttpSessionBindingEvent evt){
    System.out.println("MySessionBindingListener : valueBound() 호출됨."
        + " => Name : " + evt.getName() + ", Value : " + evt.getValue();
  }

  /**
   * HTTP 세션 영역 내에서 HttpSessionBindingListener를 구현한 객체가 언바인딩 되면 호출됨
   */
  @Override
  public void valueUnBound(HttpSessionBindingEvent evt){
    System.out.println("MySessionBindingListener : valueUnBound() 호출됨."
        + " => Name : " + evt.getName() + ", Value : " + evt.getValue();
  }
}

T10_SessionListenerTest.java

@WebServlet("/SessionListenerTest")
public class T10_SessionListenerTest extends HttpServlet{

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
  	throws ServletException, IOException {

    req.getSession().setAttribute("AAA", "AAA입니당");
    req.getSession().setAttribute("AAA", "AAA수정이에용");
    req.getSession().setAttribute("BBB", "BBB입니당");
    req.getSession().removeAttribute("AAA");
    //---------------------------------------------------

    // 속성값은 상관없고 바인딩되면 톰캣이 모니터링 하다가 valueBound()가 호출됨?
    MySessionBindingListener bindingListener = new MySessionBindingListener();

    req.getSession().setAttribute("obj1", bindingListener);
    req.getSession().removeAttribute("obj1");
  }

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
      throws ServletException, IOException {
    doGet(req, resp);
  }
}

좋은 웹페이지 즐겨찾기