[Spring Boot] Filter vs Interceptor
Spring BootFilter
J2EE 표준 스펙 기능
Client와 Dispatcher Servlet 사이에 위치하여 Dispatcher Servlet이 받는 요청과 주는 응답에 대해 검사하거나 변경할 수 있다.
- Dispatcher Servlet: HTTP 프로토콜을 통해 들어오는 모든 요청을 가장 먼저 받아서 세부 컨트롤러로 위임하는 Front Controller
- Front Controller: 서블릿 컨테이너 제일 앞단에서 서버로 오는 모든 요청을 받아 처리하는 컨트롤러
package javax.servlet;
import java.io.IOException;
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
- FilterRegistrationBean 으로 지정한 Url-Pattern에 맞는 모든 HTTP 요청이 Dispatcher Servlet으로 전달되기 전에 실행
- chain.doFilter 를 기준으로 전/후처리 작업을 지정
- destroy
- 필터 객체를 서비스에서 제거하고 사용한 자원을 반환
- 웹 컨테이너에 의해 1번 호출
Interceptor
Dispatcher Servlet과 Handler(Controller) 사이에서 동작
Spring Context 기능이며 일종의 빈이기 때문에 다른 객체(빈)에 접근이 가능.
package org.springframework.web.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.method.HandlerMethod;
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
default void postHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
@Nullable ModelAndView modelAndView
) throws Exception {
}
default void afterCompletion(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
@Nullable Exception ex
) throws Exception {
}
}
- preHandle
- 컨트롤러 전처리 작업
- 컨트롤러가 호출되기 전에 실행
- 반환값은 컨트롤러에 진입할지 여부로, true면 진입
- postHandle
- 컨트롤러 후처리 작업
- 컨트롤러가 호출된 후 실행
- @RestController 가 생긴 이후 자주 사용되지 않음
- 컨트롤러 하위 계층에서 예외 발생 시 호출되지 않음
- afterCompletion
- 컨트롤러가 호출된 후 모든 작업이 완료된 후에 실행
- 컨트롤러 하위 계층에서 예외가 발생되어도 호출된다.
class CustomIntercepter : HandlerInterceptor {
...
}
@Configuration
class WebMvcConfig : WebMvcConfigurer {
override fun addInterceptors(registry: InterceptorRegistry) {
registry.addInterceptor(CustomInterceptor())
.addPathPatterns("/*") // 적용 대상 경로
.excludePathPatterns("/sign-in") // 적용 제외 대상 경로
}
}