Servlet Filter

현시기얌·2022년 3월 21일
0

Spring MVC

목록 보기
21/22

서블릿 필터

필터 흐름

HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 컨트롤러
  • 필터를 적용하면 필터가 호출 된 다음에 서블릿이 호출된다.
  • 그래서 모든 고객의 요청 로그를 남기는 요구사항이 있다면 필터를 사용하면 된다.
  • 참고로 필터는 특정 URL 패턴에 적용할 수 있다.
  • /* 라고 하면 모든 요청에 필터가 적용된다.
  • 참고로 스프링을 사용하는 경우 서블릿은 DispatcherServlet으로 생각하면 된다.

필터 제한

HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 컨트롤러  //로그인 사용자
HTTP 요청 -> WAS -> 필터(적절하지 않은 요청이라 판단, 서블릿 호출 X) //비 로그인 사용자
  • 필터에서 적절하지 않은 요청이라고 판단하면 거기에서 끝을 낼 수 있다.
  • 로그인 여부를 체크하기에 좋다.

필터 체인

HTTP 요청 -> WAS -> 필터1 -> 필터2 -> 필터3 -> 서블릿 -> 컨트롤러
  • 필터는 체인으로 구성되는데 중간에 필터를 자유롭게 추가할 수 있다.
  • 예를 들어서 로그를 남기는 필터를 먼저 적용하고 그 다음에 로그인 여부를 체크하는 필터를 만들 수 있다.

필터 인터페이스

public interface Filter {
    
    public default void init(FilterConfig filterConfig) throws ServletException {}
    
    public void doFIlter(ServletRequest request, ServletResponse response, 
            FilterChain chain) throws IOException, ServletException;
            
    public default void destroy() {}
}
  • 필터 인터페이스를 구현하고 등록하면 서블릿 컨테이너가 필터를 싱글톤 객체로 생성하고 관리한다.
    • init() : 필터 초기화 메소드, 서블릿 컨테이너가 생성될 때 호출된다.
    • doFilter() : 클라이언트 요청이 올 때마다 해당 메소드를 호출한다. 필터의 로직을 구현하면 된다.
    • destroy() : 필터 종료 메소드, 서블릿 컨테이너가 종료될 때 호출된다.

예제 코드

@Slf4j
public class LogFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("log filter init");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("log filter doFilter");

        final HttpServletRequest httpRequest = (HttpServletRequest) request;
        final String requestURI = httpRequest.getRequestURI();

        final String uuid = UUID.randomUUID().toString();

        try {
            log.info("REQUEST [{}][{}]", uuid, requestURI);
            chain.doFilter(request,response);
        } catch (Exception e) {
            throw e;
        } finally {
            log.info("RESPONSE [{}][{}]", uuid, requestURI);
        }
    }

    @Override
    public void destroy() {
        log.info("log filter destroy");
    }
}
  • public class LogFilter implements Filter {}
    • 필터를 사용하려면 필터 인터페이스를 구현해야 한다.
  • doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    • HTTP 요청이 오면 doFilter가 호출된다.
    • ServletRequest request는 HTTP 요청이 아닌 경우까지 고려해서 만든 인터페이스다.
    • HTTP를 사용하면 HttpServletRequest httpRequest = (HttpServletRequest) request; 와 같이 다운 캐스팅 하면 된다.
  • chain.doFilter(request, response)
    • 다음 필터가 있으면 필터를 호출하고 필터가 없으면 서블릿을 호출한다.
    • 만약 이 로직을 호출하지 않으면 다음 단계로 진행되지 않는다.
@Configuration
public class WebConfig {

    @Bean
    public FilterRegistrationBean logFilter() {
        final FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(new LogFilter());
        filterRegistrationBean.setOrder(1);
        filterRegistrationBean.addUrlPatterns("/*");

        return filterRegistrationBean;
    }
}

-필터를 등록하는 방법은 여러가지가 있지만 스프링 부트를 사용한다면 FilterRegistration을 사용해서 등록하면 된다.

  • setFilter(new LogFilter()) : 등록할 필터를 지정한다.
  • setOrder(1) : 필터는 체인으로 동작한다. 순서가 낮을 수록 먼저 동작한다.
  • addUrlPatterns("/*") : 필터를 적용할 URL 패턴을 지정한다. 한번에 여러 패턴을 지정할 수 있다.
profile
현시깁니다

0개의 댓글