우선 아래의 그림을 통해 Tomcat WAS를 내장한 Spring MVC에서의 요청/응답 흐름을 이해해 놓자
(참고로, 스프링의 시작(스프링 MVC의 시작)은 서블릿, 즉 Dispatcher Servlet이다라는 점을 상기하자)
Filter의 특징
1] javax에서 제공하는 Servlet 기반 [인터페이스]이다(개발자가 직접 구현체를 만들고 등록해줘야 한다)
2] Filter 구현체는 서블릿 컨테이너(스프링 컨테이너x)에 [싱글톤]으로 저장되기에 구현체를 만들 때 stateless하게 구현을
해줘야 한다.
3] Filter 인터페이스에는 3가지 메서드가 선언돼 있다( init(), doFilter(), destroy() ).
제일 먼저 doFilter()가 호출이 된다.
4] 해당 필터를 적용한 요청 URL을 지정 가능(아래의 WebConfig 클래스 참조)
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() {}
}
@Slf4j
public class LogFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("log Filter init()");
}
// doFilter()가 제일 먼저 호출됨
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("log Filter doFilter()");
HttpServletRequest httpRequest = (HttpServletRequest) request;
String requestURI = httpRequest.getRequestURI();
String uuid = UUID.randomUUID().toString();
try{
log.info("REQUEST [{} , {}]",uuid,requestURI);
chain.doFilter(request,response); // 다음에 필터가 없으면, 서블릿 객체(Dispatcher Servlet) 호출하여 요청을 처리
}catch(Exception e){
throw e;
}
finally{
log.info("RESPONSE [{} {}]",uuid,requestURI); // 이 시점에 요청에 대한 처리(chain.doFilter(request,response))
// 가 끝난 시점!
}
}
@Override
public void destroy() {
log.info("log Filter destroy()");
}
}
위 코드 중, try의 chain.diFilter(request,response)는 다음 필터가 등록돼 있지 않으면 서블릿 객체(Dispatcher Servlet)이 호
출돼 HTTP 요청을 모두 처리한다.
해당 요청이 성공하든 실패하든 finally 부분은 항상 실행을 보장한다.
고로 Http 요청이 들어와서 요청이 처리되고 요청이 완료되기까지의 걸린 시간을 측정할 수가 있다.
이걸 통해 어떤 요청에 대해 시간부하가 많이 걸렸는 지를 파악하여 디버깅할 수가 있다.
(현재 위 코드에서는 모든 Http 요청/응답에 대한 Log 기록을 남기기 위한 용도로 Filter를 사용하고 있다)
아래 코드는 Filter 구현체를 등록하는 코드이다.
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean logFilter(){
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new LogFilter());
filterRegistrationBean.addUrlPatterns("/*"); // 어떤 요청 URL에 해당 필터를 적용을 할 것인지 세팅!
filterRegistrationBean.setOrder(1); // 이 필터 뒤에 또 다른 필터가 없으면 서블릿(Dispatcher Servlet) 호출!
return filterRegistrationBean; // 등록한 필터들이 서블릿 컨테이너에 [싱글톤]으로 등록!
}
}
'Springあるある' 카테고리의 다른 글
스프링 인터셉터(FEAT. Spring Interceptor) (0) | 2025.01.17 |
---|---|
Logback MDC(Feat. LogFilter,Filter) (0) | 2025.01.16 |
HttpServletRequest VS @SessionAttribute (0) | 2025.01.16 |
Mock 객체(Feat. Cookie,Session, Mock 객체) (0) | 2025.01.16 |
도메인의 진짜 의미! (0) | 2025.01.15 |