필터(Filter) 사용하기

필터(Filter)란?

필터는 서블릿 실행 전후에 어떤 작업을 하고자 할때 사용하는 기술이다.

 

예를 들어 서블릿이 실행되기 전 자원이 필요하다거나, 모든 각 서블릿에 한글 인코딩 , 시간 측정등과 같은 반복적으로 처리해야 하는 공통 작업을 미리 필터에서 처리하여 번거로움이 줄어든다.

 

필터는 용도에 따라 2 가지로 나뉜다.

  • 요청 필터
    • 인코딩 기능
    • 사용자 인증 및 권한 검사
    • 요청 시 요청 관련 로그 작업

  • 응답 필터
    • 서비스 시간 측정
    • 응답 결과에 대한 암호화 작업

 

필터 관련 API

  • javax.servlet.Filter
    • init(): 필터 생성 시 컨테이너에 의해 호출되어 초기화 작업을 수행
    • doFilter(): 요청/응답 시 컨테이너에 의해 호출되어 기능을 수행
    • destory(): 필터 소멸 시 컨테이너에 의해 호출되어 종료 작업을 수행

  • javax.servlet.FilterConfig
    • getFilterName(): 필터 이름을 반환
    • getInitParameter(String name): name에 대한 값을 반환
    • getServletContext(): Servlet Context 객체를 반환
  • java.servlet.FilterChain

 

 

 

Filter 매핑 하는 방법

web.xml 설정

<!--컨텍스트 초기화 매개변수-->
	...
    
    <!-- 필터 선언 -->
    <filter>
    	<filter-name>필터의 별명</filter-name>
        <filter-class>필터의 클래스 이름</filter-class>
        
        <init-param>
        	<param-name>파라미터 이름</param-name>
            <param-value>파라미터 값</param-value>
        </init-param>
	<filter>
    
    
    <!-- 필터 URL 매핑 -->
    <filter-mapping>
    	<filter-name>위에 정의한 필터의 별명</filter-name>
        <url-pattern>필터가 적용되어야 하는 URL</url-pattern>
    </filter-mapping>
    
    
    <!-- 서블릿 선언 -->
    
    <!-- 서블릿을 URL과 연결 -->

Servlet 2.4 이상부터 순서에 상관없이 태그를 작성할 수 있다.

 

어노테이션으로 등록

@WebFilter(
	urlPatterns="/*",
    initParams={
    	@WebInitParam(name="encoding", value="UTF-8")
    })
public class 클래스명 implements Filter{
	FilterConfig config;

 

 

필터 예제: 한글 인코딩 (어노테이션 설정 방법)

서블릿에서 getParameter()를 호출했을 때 한글이 깨지는 현상을 처리하기 위해 우리는 지금까지 요청(requset)에 인코딩 설정을 해주었다.

 

request.setCharacterEncoding("UTF-8");

 

하지만 각 서블릿 마다 이 코드를 작성하는 것은 번거로운 일이다. 바로 이 때, 서블릿 필터(Filter)를 이용하면 간단하게 처리할 수 있다.

 

필터 클래스를 작업하기 위해서는 javax.servlet.Filter 인터페이스를 구현해야 한다.

 

EncoderFilter.java

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;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;

@WebFilter(
	urlPatterns="/*",
	initParams={
		@WebInitParam(name="encoding",value="UTF-8")
	})
public class EncoderFilter implements Filter{
	FilterConfig config;
	
	@Override
	public void init(FilterConfig config) throws ServletException {
		this.config = config;
	}
	
	//필터와 연결된 URL에 대해 요청이 들어오면 doFilter()가 항상 호출된다.
	//따라서 이 메소드에 필터가 할 일을 작성하면 된다.
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain nextFilter) 
    													throws IOException, ServletException {
		//서블릿이 실행되기 전에 해야 할 작업
		request.setCharacterEncoding(config.getInitParameter("encoding"));
		
		
		//다음 필터를 호출. 더 이상 필터가 없다면 원래 서블릿의 서비스가 동작 
		nextFilter.doFilter(request, response);
		
		//서블릿을 실행한 후, 클라이언트에게 응답하기 전에 해야할 작업
		
	}

	@Override
	public void destroy() {}
}

 

위 코드에도 설명을 한 것처럼

 

nextFilter.doFilter(request, response) 를 기준으로

전에 작성된 코드들은 요청 필터 기능

후에 작성된 코드들은 응답 필터 기능

 

 

 

필터(Filter)의 구동 순서

  1. 서블릿 컨테이너는 웹 애플리케이션을 시작할 때 배치기술서(web.xml)에 등록된 필터(Filter)의 인스턴스를 생성한다.
  2. 또한 생성된 필터(Filter)에 대해 준비작업을 할 수 있도록 init()를 호출한다.
  3. 클라이언트의 요청이 들어오면 그 요청에 해당하는 필터의 doFilter() 메소드를 호출한다.
  4. doFilter()에서 작업을 실행하고 다음 필터의 doFilter() 메소드를 호출하고 이 과정을 마지막 필터(Filter)까지 반복한다.
  5. 더 이상 호출할 필터(Filter)가 없다면 서블릿의 service()를 호출한다.
  6. service()호출이 끝나면 각 필터(Filter)들에 남은 코드를 실행한다.
  7. 마지막으로 클라이언트에게 응답 결과를 보낸다.