스프링 외부의 서블릿에서 제공하는 공통처리 기능
스프링 내로 요청이 들어오기 전과 스프링의 요청이 나갈 때 처리 가능
조금 더 low level 처리가 가능
좋은 레스토랑에 처음 들어갈 때 옷에 묻은 먼지를 털듯 제일 앞에서 필터링 해주는 곳
스프링에서 제공하는 공통처리 기능
실제 매핑된 Handler 정보 확인 가능(어떤 것이 실제 내 요청을 처리하는지도 확인 가능)
조금 더 상세한 조건식과, 세부적인 스펙(pre, post, after)를 통해 구체적인 시점에 구체적인 동작 가능
AOP와 비교한다면 AOP는 인터셉터보다 더 구체적인 조건(애노테이션, 파라미터, 주소 등)과 동작 위치(afterThrowing)을 갖음
놀이동산에 입장은 했는데 빅5나, 자유이용권을 뽑는 것과 비슷! AOP는 특정 놀이기구 하나를 타는 것
AOP - Java관련
인터셉터 - URL관련
Component 빈 등록
@Slf4j
@Component
public class LogFilter implements Filter{
@Override
public void doFilter(
ServletRequest request, ServeletResponse response, FilterChain chain
) throws ServletException, IOException {
log.info("Hello filter : " + Thread.currentThreadd());
chain.doFilter(request, response);
log.info("Bye filter :" + Thread.currentThread());
}
}
필터 실습 코드(요청/응답 로깅)
인증(로그인)등 웹 관련된 공통 관심사를 처리할 때는 HTTP 헤더나 URL 정보들이 필요하기 때문에 웹과 관련된 기술들이 필요함
샘플코드(요청 로그)
설정을 통해 filter 등록
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean loggingFilter(){
// Filter들이 다중으로 존재하는 경우 Configuration을 사용한다.
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new LogFilter());
filterRegistrationBean.setOrder(1);
filterRegistrationBean.addUrlPatterns("/payment"); // 특정 URL 패턴에 필터 걸기
return filterRegistrationBean;
}
}
package com.example.demo.config;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Slf4j
public class LogInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("preHandle LogInterceptor : " + Thread.currentThread());
log.info("preHandle handler : " + handler);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 응답
log.info("postHandle LogInterceptor : " + Thread.currentThread());
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 요청이 성공하든 실패하든 무조건 온다.
log.info("afterHandle LogInterceptor : " + Thread.currentThread());
if(ex != null){
log.error("afterCompletion exception : " + ex.getMessage());
}
}
}
인터셉터 실습
로깅 샘플 코드 작성
필터와 동일한 기능을 하는 코드를 작성할 수 있음
다만 더 세밀한 조건식(include, exclude 등)과 preHandle, postHandle, afterComplete를 통한 다양한 처리 가능
interceptor를 등록하기 위해선 WebMvcConfigurer를 구현해야 한다.
package com.example.demo.config;
import jakarta.servlet.Filter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer { // interceptor를 등록하려면 WebMvcConfigurer을 등록해주어야 한다.
@Bean
public FilterRegistrationBean loggingFilter(){
// Filter들이 다중으로 존재하는 경우 Configuration을 사용한다.
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new LogFilter());
filterRegistrationBean.setOrder(1);
filterRegistrationBean.addUrlPatterns("/order/*"); // 특정 URL 패턴에 필터 걸기
return filterRegistrationBean;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor())
.order(1)
.addPathPatterns("/**") // 추가
.excludePathPatterns("/css/*", "/images/*"); // 정적 파일 제거
}
}