HTTP 요청 → WAS(톰캣) → 필터 → 서블릿 (디스페처 서블릿) → 컨트롤러
필터란, 클라이언트의 요청을 중간에 낚아채서 로직을 처리하기 위해 제공되는 기능이다.
필터는 여러 체인으로 구성되며, 프로그래머가 정한 순서에 맞게 해당 로직을 처리할 수 있도록 한다.
doFilter 메서드를 통해 원하는 로직을 구현하면 되고, 만약 필터를 진행하다 로직이 실패하면 다음 순서로 진행되지 않고 바로 WAS로 올라가게 된다.
package jakarta.servlet;
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() {}
}
필터 인터페이스를 상속받아서 구현하면 되며, 구현체를 등록하면 IoC 컨테이너는 이를 싱글톤 Bean으로 생성하고 관리한다.
void init()
void doFilter()
chain.doFilter
를 호출해주어야 한다.void destory()
@Slf4j
public class LogFilter implements Filter {
@Override
public void init(
FilterConfig filterConfig
) throws ServletException {
log.info("log filter init");
}
@Override
public void destroy() {
log.info("log filter destroy");
}
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain
) throws IOException, ServletException {
log.info("log filter doFilter");
HttpServletRequest req = (HttpServletRequest) request;
String requestURI = req.getRequestURI();
String uuid = UUID.randomUUID().toString();
try {
log.info("REQUEST [{}][{}]", uuid, requestURI);
chain.doFilter(request, response);
} catch (Exception e) {
log.error("Filter Error: [{}]", (Object) e.getStackTrace());
throw e;
} finally {
log.info("RESPONSE [{}][{}]", uuid, requestURI);
}
}
}
WAS → 필터 1 → 필터 2 → 서블릿 → 컨트롤러 → 서블릿 → 필터 2 → 필터 1 → WAS
필터는 서블릿이 호출되기전에 호출되며, doFilter 내부에서 다음 chain의 doFilter 메서드를 호출하는 방식으로 진행되므로 위과 같은 흐름으로 진행된다.
chain.doFilter(request, response);
를 생략하게 되면 다음 순서로 진행되지 않으며, 함수는 종료되고 WAS로 올라가게 된다.
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<Filter> logFilter() {
FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();
bean.setFilter(new LogFilter());
bean.setOrder(1);
bean.addUrlPatterns("/*");
return bean;
}
}
위와 같이 @Configuration
애노테이션이 붙은 클래스에 Spring Bean으로 등록하면 된다.
public void setFilter(T *filter*)
public void setOrder(int *order*)
public void addUrlPatterns(String... *urlPatterns*)
public void setUrlPatterns(Collection<String> *urlPatterns*)