[스프링 MVC] 서블릿 필터를 어떻게 스프링 빈으로 관리할 수 있을까?
서블릿 필터는 서블릿 컨테이너 영역입니다.
그런데 우리는 서블릿 필터 구현체를 작성하고 빈으로 등록할 수 있습니다.
필터 인터페이스
public interface Filter {
public default void init(FilterConfig filterConfig) throws ServletException {}
public void doFilter(ServletRequest request, ServletRpesponse response, FilterChain chain) throws IOException, SevletException;
public default void destory() {}
}
필터 인터페이스를 구현하고 빈(Bean)으로 등록하면
서블릿 컨테이너가 필터를 싱글톤 객체로 생성하고, 관리할 수 있습니다.
서블릿 필터는 서블릿 컨테이너의 영역에 속하지만,
스프링은 서블릿 컨테이너의 기능을 통해 필터를 관리할 수 있도록 지원합니다.!!!
어떻게 이런일이 가능 할까요? 🤔
먼저 보는 결론
DelegatingFilterProxy
이전: 서블릿 필터는 스프링 컨테이너에서 관리할 수 없음DelegatingFilterProxy
이후:DelegatingFilterProxy
를 통해 스프링 빈으로 필터를 등록할 수 있음- 스프링 부트 등장 이후: 내장 톰캣을 사용하는 스프링 부트의 등장으로
DelegatingFilterProxy
를 거치치 않고 바로 필터를 등록할 수 있음
서블릿 필터가 뭔데?
먼저 서블릿 필터가 뭔지 모를 수 있습니다.
Client로 부터 Server로 요청이 들어오기 전에 서블릿을 거쳐서 필터링 하는 것을 서블릿 필터라고 합니다.
스프링으로 개발한 웹 애플리케이션에 HTTP
요청을 하면,
웹 애플리케이션은 어떤 과정을 통해서 이를 처리할까요?
흐름
HTTP 요청 -> WAS -> 필터 -> 디스패처 서블릿 -> 컨트롤러
흐름을 보면 스프링 컨테이너로 요청이 오기전에 서블릿 컨테이너에서 먼저 요청을 처리하는 것을 알 수 있습니다.
Client로 부터 Server로 요청이 들어오기 전에 서블릿을 거쳐서 필터링 하는 것을 서블릿 필터라고 합니다.
공통적인 기능들을 서블릿이 호출되기 전에 수행(전처리)되게 하고 싶거나
서블릿이 호출 되고 난 뒤에 수행(후처리) 하고 싶으면 공통적인 기능들을 서블릿 필터로 구현하면 됩니다.
HTTP 요청 -> WAS -> 필터(요청 판단) -> 디스패처 서블릿 -> 컨트롤러
정리
서블릿이 호출되기 전, 후에 공통적인 기능(웹 공통 로직)을 추가할 때 사용한다.!
참고
- 필터는 체인으로 구성되는데, 중간에 필터를 자유롭게 추가할 수 있습니다.
아니 어떻게 서블릿 컨테이너에 있는 것을 스프링 컨테이너에서 관리할 수 있는거야? 🤔
상식적으로 서블릿 컨테이너의 필터가 스프링 컨테이너에서 관리 될 수 있다는 것은 이상합니다. 🫨
하지만, 위처럼 필터를 구현하면 스프링 빈으로 등록 가능하다는 것을 알 수 있습니다.
옛날에는 실제로 필터가 스프링 컨테이너에 의해 관리될 수 없었습니다.
그런데 DelegatingFilterProxy
와 SpringBoot
가 등장하면서 얘기가 달라졌습니다.
DelegatingFilterProxy 두두등장!
필터에도 DI
와 같은 스프링 기술이 필요한 상황이 발생하면서,
등장한 기술이 바로 DelegatingFilterProxy
입니다.
DelegatingFilterProxy
는 서블릿 컨테이너에서 관리되는 프록시용 필터이고,
우리가 커스텀한 필터를 가지고 있습니다.
우리가 커스텀한 필터는 스프링 컨테이너에서 관리되는데,
요청이 오면 DelegatingFilterProxy
가 요청을 받아서 우리가 커스텀한 필터에 요청을 위임합니다.
1. Filter 구현체(커스텀한 필터)가 스프링 빈으로 등록
2. SeveletContext가 Filter 구현체를 갖는 DelegatingFilterProxy를 생성
3. SeveletContext가 DelegatingFilterProxy를 서블릿 컨테이너에 필터로 등록
4. 요청이 오면 DelegatingFilterProxy가 필터 구현체에게 요청을 위임하여 필터 처리를 진행
스프링 부트를 사용하면 내장 톰캣을 지원하기 때문에
톰캣과 같은 서블릿 컨테이너까지 스프링 부트가 제어 가능합니다.
따라서 ServletContext
에 우리가 커스텀한 필터 빈을 DelegatingFilterProxy
로 감싸서 등록하지 않아도 됩니다!!
스프링 부트가 서블릿 필터의 구현체 빈을 찾으면 DelegatingFilterProxy
없이 바로 필터 체인에 필터를 등록해주기 때문입니다.^^👍
간단하게 테스트 해보자..!
CustomFilter
@Component
public class CustomFilter implements Filter {
// 필터 초기화 메소드, 서블릿 컨테이너가 생성될 때 호출
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
// 요청을 실행하는 메소드, 필터가 여러개면 다음 필터를 호출한다.
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
LocalDateTime now = LocalDateTime.now();
System.out.println("["+now+"] 너 정말로 DelegatingFilterProxy 에 등록안해줘도 되는거니?");
chain.doFilter(request, response);
}
// 필터 종료 메소드, 서블릿 컨테이너가 종료될 때 호출
@Override
public void destroy() {
Filter.super.destroy();
}
}
TestController
@RestController
public class TestController {
@GetMapping("/")
public String test() {
LocalDateTime now = LocalDateTime.now();
return now.toString();
}
}
결과
결과(시간)를 보면 CustomFilter
가 먼저 요청을 받은 것을 알 수 있습니다.^^
참고
Spring 필터(Filter)가 스프링 빈 등록과 주입이 가능한 이유(DelegatingFilterProxy의 등장) - (2) - MangKyu’s Diary
'0+ 스프링 > 0+ 스프링 MVC' 카테고리의 다른 글
[스프링 MVC] 어떻게 컨트롤러는 다양한 종류의 파라미터를 받아서 처리할 수 있을까? 🤔 (0) | 2023.05.27 |
---|---|
[스프링 MVC] 서블릿 필터가 있는데 인터셉터는 왜 나온거지? (0) | 2023.05.26 |
[스프링 MVC] 서블릿 필터 예외처리 방법 (0) | 2023.05.26 |
[스프링 MVC] XML 데이터 파싱(RestTemplate) (0) | 2023.05.06 |
[스프링 MVC] Java에서 서블릿이 등장한 이유(Feat. 서블릿 기초 개념) (0) | 2023.03.28 |