필터를 구현하기 위해 Servlet/Jsp에서는 javax.servlet.Filter라는 인터페이스를 제공하며 이 인터페이스를 구현하도록 되어 있습니다. Filter 인터페이스의 메서드는 다음과 같이 구성되어있습니다.
package javax.servlet;
 
import java.io.IOException;
 
public interface Filter {
 
    public void init(FilterConfig filterConfig) throws ServletException;
    
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException; 
 
 
    public void destroy();
}
cs


public void init(FilterConfig filterConfig)
웹컨테이너(톰캣)이 시작될 때 필터 객체를 생성하는데, 이때 객체가 생성되면서 최초에 한 번 호출되는 메서드입니다. FilterConfig 객체를 넘겨주기 때문에 이를 통해 여러가지 설정값을 넘겨받을 수 있고 필터에서 처리시 필요한 객체등을 초기화(예를들어 JDBC 커넥션 등) 하는데 사용됩니다.

public void destroy()
필터 객체가 제거될 때 실행되는 메서드입니다. 보통 초기화시 생성했던 자원들을 종료하는 기능에 사용됩니다.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
필터의 핵심 메서드입니다. doFilter()는 클라이언트의 요청이 있을때마다 매번 실행됩니다. ServletRequest와 ServletResponse 객체를 넘겨주기 때문에 이를 가지고 요청과 응답을 조작할 수 있습니다. 그리고 FilterChain을 통해 조작 이후 요청을 원래 목적지인 서블릿으로 전달할 수 있습니다.



필터 구현 및 등록 예제
요청이 들어왔을 때 Logging처리를 하는 필터를 구현해보도록 하겠습니다. 필터를 구현한 후에 web.xml에 등록해주기만 하면 끝입니다.
LoggingFilter.java가 필터를 구현한 클래스이며, web.xml에 필터 설정을 등록할 것입니다. 이후 브라우저를 통해 dest.jsp를 호출하여 필터를 거쳐가는지 테스트해볼 것입니다. 아래의 프로젝트 구조를 참고하고 예제 소스를 작성해 보도록 하겠습니다.




LoggingFilter.java
필터 클래스는 javax.servlet.FIlter 인터페이스를 상속받아 구현하면 됩니다. 초기화시(init), 요청과 응답이 필터를 거쳐가는 순간(doFilter)에 콘솔로그가 출력 되도록 하였습니다.
핵심은 doFilter()메서드 입니다. 서블릿에서 익숙하게 사용했던 request와 response가 매개변수로 넘어오므로 이들을 통해 필터에서 여러가지 기능을 처리할 수 있습니다. 이후 FilterChain을 통해서 이 다음에 거쳐야 할 또다른 필터나 서블릿으로 요청을 전달합니다. 요청을 전달할때는 필터체인의 doFilter()메서드를 사용하면 되며, 이때 역시 request와 response를 넘겨줍니다.
package test;
 
 
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
 
 
public class LoggingFilter implements Filter {
    /**
     * 필터가 생성될 때 초기화시 사용
     */
    public void init(FilterConfig config) throws ServletException {
        System.out.println("필터 초기화 됨");
    }
    
    /**
     * 요청시마다 필터가 실행할 메서드
     */
    public void doFilter(ServletRequest request, ServletResponse  response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("요청이 필터에서 처리됨");
        chain.doFilter(request, response);
        System.out.println("응답이 필터에서 처리됨");
    }
 
 
    /**
     * 필터가 제거될 때 실행
     */
    public void destroy() {
        System.out.println("필터 제거됨.");
    }
}
cs

 

 



web.xml
      <filter>
            <filter-name>loggingFilter</filter-name>
            <filter-class>test.LoggingFilter</filter-class>
      </filter>
 
 
      <filter-mapping>
            <filter-name>loggingFilter</filter-name>
            <url-pattern>*.jsp</url-pattern>
      </filter-mapping>
cs

web.xml에서는 구현한 필터를 등록하고 URL을 맵핑시킵니다. 필터라고 해서 모든 요청을 다 처리할 필요는 없을것입니다. 특정 요청시에만 필터가 동작하도록 설정할 수도 있습니다.

<filter>
필터태그에서는 필터를 등록할 수 있습니다. <filter-name>에는 필터의 이름을 지정합니다. <filter-class>에서는 구현한 필터 클래스를 패키지명을 포함하여 지정해줍니다. 웹 컨테이너는 서버를 띄울 때 web.xml 설정의 <filter> 태그를 읽어들여 필터 객체를 생성하고 초기화합니다.

<filter-mapping>
등록한 필터의 동작할 범위(대상)을 설정할 수 있습니다. <filter-name>은 앞서 등록한 필터명을 지정합니다. <url-pattern>에는 URL 패턴을 입력하는데, 서블릿을 설정할때와 규칙이 같습니다. *.jsp로 지정해 주었기에 브라우저로부터 모든 jsp 요청시에는 작성한 로깅필터가 동작합니다.



특정 서블릿을 대상으로 필터링 하고싶은 경우
아래와 같이 <servlet-name> 태그를 사용할 수 있는데 필터링할 서블릿의 이름을 지정하면 됩니다. 이때 서블릿 이름은 web.xml에서 <sevlet> 태그로 등록한 서블릿의 <servlet-name>을 통해서 설정한 이름이어야 합니다. 즉 서블릿 클래스명이 아닌 web.xml에서 등록한 서블릿의 이름이어야 합니다.
      <filter-mapping>
            <filter-name>loggingFilter</filter-name>
            <servlet-name>등록한 서블릿 이름</servlet-name>
      </filter-mapping>
cs

 

 

 

하나의 필터에 여러개의 URL 등록하는 경우
하나의 필터에 여러개의 URL을 등록하고 싶은 경우 다음과 같이 <url-pattern> 태그를 여러개 등록하면 됩니다. <url-pattern>뿐만 아니라 <servlet-name> 태그도 같이 사용 가능합니다.
<filer-mapping>
    <filter-name>thirdFilter</filter-name>
    <url-pattern>/urlone</url-pattern>
    <url-pattern>/urltwo</url-pattern>
    <url-pattern>/urltree</url-pattern>
    <servlet-name>fourServlet</servlet-name>
</filer-mapping>
cs

 




dest.jsp
브라우저에서 테스트로 호출할 대상이 필요하므로 dest.jsp를 작성합니다.
<%@ page contentType="text/html; charset=utf-8"%>
 
 
<html>
<head>
</head>
<body>
      <%
            System.out.println("목적지 JSP 호출됨");
      %>
      
      <h1>목적지 JSP 호출됨</h1>
</body>
</html>
cs


테스트
필터를 작성하고 설정이 되었다면 톰캣을 시작합니다. 브라우저를 통해 localhost/des.jsp를 두 번 호출하면 이클립스의 콘솔창에는 다음과 같이 로그가 찍히게 됩니다. 최초에 톰캣이 시작될 때 "필터 초기화 됨"이 출력되고 이후에 jsp 페이지를 요청할때마다 요청과 응답이 처리되었다는 로그가 찍히게 됩니다.
필터 초기화 됨
요청이 필터에서 처리됨
목적지 JSP 호출됨
응답이 필터에서 처리됨
요청이 필터에서 처리됨
목적지 JSP 호출됨
응답이 필터에서 처리됨
cs


이후 브라우저에는 최종 결과가 응답되어 출력됩니다.




관련글
블로그 이미지

도로락

IT, 프로그래밍, 컴퓨터 활용 정보 등을 위한 블로그

댓글을 달아 주세요! 질문 환영합니다!

  • 질문자 2020.07.21 22:16  댓글주소  수정/삭제  댓글쓰기

    안녕하세요 글 내용중에 응답을 조작하는 것도 가능하다고 하셨는데 이전 필터에서 객체에 할당된 값이나 에러메시지를 다음 필터에서 변경할 수도있나요?
    dofilter로 전달되는 servletrequest와 response는 클라이언트에서의 특정한 요청내에서 공유되는 개념이 맞나요?
    감사합니다

  • 자바 새내기 2022.01.10 11:22  댓글주소  수정/삭제  댓글쓰기

    안녕하세요 블로그 잘 봤습니다.
    선생님 요청이 필터에서 '처리됨이 출력 되고', '목적지 JSP 호출됨' 이 출력 되려면 dest.jsp 가야 되는데 어떻게 가는지 알 수 있을까요?