리루

3. Servlet (써블릿) - 써블릿 리스터와 필터 본문

#Spring

3. Servlet (써블릿) - 써블릿 리스터와 필터

뚱보리루 2020. 2. 2. 15:49

1. 서블릿 리스너

 - 웹 애플리케이션에서 발생하는 주요 이벤트를 감지하고 각 이벤트에 특별한 작업이 필요한 경우에 사용할 수 있다.

 - 서블릿 컨테이너에서 발생하는 이벤트(서블릿 라이크사이클의 변화, 애트리뷰트의 변화, 세션의 변화)

 - 여러개의 서블릿이 공톡적으로 사용할 객체들을 넣어놓는 등의 목적으로 사용할 수 있다.(DB 연결 등)

 

 

2. 서블릿 필터

 - 요청이 서블릿의 doGet으로 바로가기 전에 전처리 및 응답에 처리를 하기위해서 사용.

 - 들어온 요청을 서블릿으로 보내고 또 서블릿이 작성한 응답을 클라이언트로 보내기 전에 특별한 처리가 필요한 경우에 사용된다.

 - 체인 형태의 구조를 갖는다.(순차적으로 적용된다, 반드시 다음 체인으로 넘어가도록 코드를 작성해줘야 한다.)

 

 

3. 서블릿 리스너 실습

 - Servlet Listener 생성

package me.json;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyListener implements ServletContextListener {

    // Servlet Context 의 Lifecycle 을 감지할 수 있는 interface 구현
    // Override interfaces those can detect lifecycle of Servlet Context
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("Context Listener Initialized");
        sce.getServletContext().setAttribute("name", "json");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("Context Destroyed");
    }
}

 

 - web.xml에 Servlet listener 등록

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <!-- Register Servlet Listener-->
  <listener>
    <listener-class>me.json.MyListener</listener-class>
  </listener>


  <!-- Register servlet -->
  <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>me.json.HelloServlet</servlet-class>
  </servlet>


  <!-- Mapping Servlet with url pattern -->
  <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>

</web-app>

 

 - Servlet에서 listener 활용

package me.json;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class HelloServlet extends HttpServlet {

    @Override
    public void init() throws ServletException {
        System.out.println("init");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet");
        resp.getWriter().print("<html>");
        resp.getWriter().print("<head>");
        resp.getWriter().print("<body>");
        resp.getWriter().print("<h1>Hello Servlet</h1>");
        resp.getWriter().print("<h1>Hello" + getName() + "</h1>");
        resp.getWriter().print("</body>");
        resp.getWriter().print("</head>");
        resp.getWriter().print("</html>");
    }
    
    private Object getName() {
        // Get attribute value that is set in the Servlet listener
        return getServletContext().getAttribute("name");
    }

    @Override
    public void destroy() {
        System.out.println("destroy");
    }
}

 

4. 서블릿 필터 실습

 - 서블릿 필터 생성

package me.json;

import javax.servlet.*;
import java.io.IOException;

public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("Filter Initialized");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("doFilter : MyFilter");

        // Have to connect to next filter(if this is last filter this will be connected to servlet) : Chaining
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        System.out.println("Filter Destroyed");
    }
}

 - web.xml에 서블릿 필터 등록

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <!-- Register a filter -->
  <filter>
    <filter-name>myFilter</filter-name>
    <filter-class>me.json.MyFilter</filter-class>
  </filter>


  <!-- Mapping filter to servlet-->
  <filter-mapping>
    <filter-name>myFilter</filter-name>
    <servlet-name>hello</servlet-name>
  </filter-mapping>

  <!-- Register Servlet Listener-->
  <listener>
    <listener-class>me.json.MyListener</listener-class>
  </listener>


  <!-- Register servlet -->
  <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>me.json.HelloServlet</servlet-class>
  </servlet>


  <!-- Mapping Servlet with url pattern -->
  <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>

</web-app>

 

5. 결과

 - 아래와 같이 , Context Listener Init과 Filter Init은 호출이 없어도 먼저 호출된다. 해당 이유는 Init 할때 오래 걸릴 수 있는 시간을 미리 1회 호출해 둠으로써 Init 과정을 완료시켜버린다. 이를 '웜업' 이라고 한다.

 

 

[참고] Infrean 백기선의 스프링 웹 MVC 기반으로 저같은 초보들이 알기 쉽도록 재구성 해보았습니다., (매우 유용하고 친절한 강의라고 생각합니다. 들으시면 기본적인 구조나 원래를 익히는데 도움이 되실 것 같습니다!! 20% 할인하는 기간도 간간히 있으니 잘 활용하세용~)