본문 바로가기
웹개발/spring

스프링 Filter 와 Listener

by heavenLake 2022. 2. 16.
반응형

 

 원본사이트

https://galid1.tistory.com/521?category=783055 

 

SpringMVC - Spring MVC 동작원리 - 1 (Servlet의 Listener와 Filter)

SpringMVC의 동작 원리 - 1 이제부터는 SpringMVC의 동작원리에 대해서 알아보는 시간을 가지며 포스팅을 할 예정입니다. 일반 java WebProject에서 부터 Spring MVC 프로젝트를 생성하기까지 천천히 알아보

galid1.tistory.com

이제부터는 SpringMVC의 동작원리에 대해서 알아보는 시간을 가지며 포스팅을 할 예정입니다. 일반 java WebProject에서 부터 Spring MVC 프로젝트를 생성하기까지 천천히 알아보면서 진행하겠습니다. 우선 SpringMVC의 동작 원리를 알아보기에 앞서서 Spring의 기반인 Servlet의 기능중 Listener  Filter를 알아보겠습니다. SpringMVC는 Servlet 기반의 웹어플리케이션을 쉽게 만들수 있게 도와주는 프레임워크 이기 때문입니다.

 

출처 : https://stargatex.wordpress.com/2015/12/08/spring-mvc-request-lifecycle/

 

1. ServletWeb Project 생성

이전 포스팅에서 Eclipse를 기반으로 Servlet Project를 생성하는 방법을 올렸었는데 앞으로는 Intelli J에서 포스팅을 진행할 것이므로 Intelli J 에서 ServletWeb Projet를 생성하는 방법을 우선 알아보도록 하겠습니다.

 

1.1 프로젝트 생성

file -> new Project를 클릭한 뒤 좌측의 Maven을 클릭합니다. 그 후 Create from archetype을 체크하고 하단의 목록중 org.apache.cocoon-22-archetype-webapp을 클릭하여 Project를 생성합니다.

 

1.2 의존성

우선 Servlet을 사용하기 위해서는 Servlet-api에 대한 의존성을 추가해주어야 합니다. 

 

 

2. Listener

Servlet의 Listener는 웹어플리케이션의 주요 변화를 감지하기 때문에 그 이벤트가 발생했을 때 특별한 작업을 처리하도록 할 수 있습니다. 간단히 ServletContext의 라이프 사이클 이벤트를 예제로 들며 설명드리겠습니다.

ServletContext 수준의 이벤트

- Context 라이프 사이클 이벤트

- Context Attribute 수정 이벤트

Session 수준의 이벤트

- Session 라이프 사이클 이벤트

- Session Attribute 수정 이벤트

 

2.1 ServletContextListener

ServletContextListener은 Context의 라이프사이클을 감시하는 기능을 제공합니다. 즉, 웹어플리케이션의 시작과 종료시 다음의 메소드가 자동으로 호출 됩니다. contextInitialized(), contextDestoryed() 예제를 보며 설명드리겠습니다.

 

예제구조

예제를 진행하기 전에 간단히 프로젝트 구조를 보여드리면 조금 더 실습하기 수월할 것 같아 첨부해 두었습니다.

 

MyListener

 
public class MyListener implements ServletContextListener {
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("Context가 초기화 되었습니다.");
        sce.getServletContext().setAttribute("name", "galid");
    }
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("Context가 파기 되었습니다.");
    }
}

간단히 MyListener Class를 생성한 뒤 Context 라이프 사이클 이벤트를 감지하기 위해 ServletContextListener Interface를 구현하고 contextInitialized(), contextDestroyed()메소드를 구현했습니다. 구현한 각각의 메소드에서는 언제 호출되었는지 확인하기 위해 출력하는 코드를 추가했고, contextInitialized() 메소드에서는 Context에 "name"을 키값으로 "galid"라는 데이터를 기입해주었습니다.

 

web.xml

그 후 ServletContainer에서 Listener가 무엇인지를 알 수 있도록 web.xml에 listener를 등록해주어야 합니다. servlet을 매핑하는 방법은 이전 포스팅을 참고해주세요.

 

HelloServlet

 
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet");
        resp.getWriter().println("<html><body>");
        resp.getWriter().println("<h1> Hello Servlet </h1><br/>");
        resp.getWriter().println("hi " + getServletContext().getAttribute("name"));
        resp.getWriter().println("</body></html>");
    }
}

HelloServlet에서는 간단한 페이지를 반환합니다. 다만 Context가 초기화 될때 기입된 Attribute을 "name"키값을 이용해 가져와 출력하도록 했습니다.

 

결과

 

  

 

3. Filter

Listener의 경우에는 웹어플리케이션에 발생한 주요 이벤트를 감지하고 그 이벤트 이전에 특별한 작업을 처리 할 수 있다고 설명드렸습니다. 그에 반해 Filter는 사용자에게 온 요청을 Servlet에게 전달하기 전에 특별한 처리를 할 수 있도록 해줍니다. 바로 예제를 통해 Filter를 사용하는 방법과 동작 과정을 알아보도록 하겠습니다.

 

3.1 Filter

예제구조

 

 

MyFilter

 
public class MyFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("Filter Init");
    }
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("Filtering");
        filterChain.doFilter(servletRequest, servletResponse);
    }
    public void destroy() {
        System.out.println("Filter Destory");
    }
}

먼저 Filter Interface를 구현하는 MyFilter Class를 생성합니다. 구현 되는 세가지 메소드는 각각 다음과 같습니다.

1. init

- ServletContainer에 Filter가 등록되어 초기화 될때 실행됩니다.

2. doFilter

- Filter가 매핑된 Servlet에 사용자의 요청이 들어왔을때 Servlet에게 전달하기 전 실행됩니다.

3. destroy

- ServletContainer가 종료되기전 Filter가 삭제될때 호출됩니다.

 

doFilter에서 중요한점은 파라미터로 전달되는 FilterChain의 doFilter()를 호출해주어야 다음 filter로 전달되고 결국 servlet에게 요청이 전달될 수 있다는 것입니다. doFilter()를 호출하지 않는다면 해당 filter에서 사용자의 요청이 그냥 걸러지게 되어 servlet에게 요청이 전달되지 않습니다.

 

web.xml

역시나 Filter도 web.xml에 등록해야 ServletContainer에서 Filter를 인식할 수 있습니다. <filter> 태그는 말그대로 Container에 어떤 Class가 Filter인지를 알려주기위한 태그이며, <filter-mapping>태그는 어떤 filter가 어떤 Servlet에 대해 Filter를 할지를 정해주는 태그입니다. 위의 경우 미리 등록한 helloServlet이란 요청에대해 filter를 하도록 했습니다.

 

결과

우선 Servlet Container를 구동시켰습니다. Welcome Page를 작성해놓지 않았기 때문에 404error가 떳지만 일단 무시해도 됩니다. 바로 아래를 보시면 Filter의 init() 메소드가 호출된 것을 알 수 있습니다. 이를 통해 각각의 Filter들은 Servlet Container가 초기화되는 과정에서 모두 등록되어 init()을 호출한다는 것을 알 수 있습니다.

 

그 후 helloServlet에 요청을 보내어보았습니다. 요청된 Servlet의 doGet()이 호출되기 이전 Filter의 doFilter()가 먼저 호출됨을 알 수 있습니다.

 

 

 

반응형

'웹개발 > spring' 카테고리의 다른 글

Spring Boot 프로젝트 생성  (0) 2022.07.01
스프링 properties 읽어오기  (0) 2022.02.17
스프링 Bean의 개념과 Bean Scope 종류  (0) 2022.02.16
스프링 필터 (필터와 인터셉터 차이점)  (0) 2022.02.16
스프링 Listener  (0) 2022.02.16

댓글