본문 바로가기

Develop/Spring

Spring Filter, Interceptor

728x90

필터와 인터셉터의 차이

필터

  • 스프링 외부의 서블릿에서 제공하는 공통처리 기능
  • 스프링 내로 요청이 들어오기 전과 스프링의 요청이 나갈 때 처리 가능
  • 조금 더 Low level 처리가 가능
  • 좋은 레스토랑에 처음 들어갈 때 옷에 묻은 먼지를 털듯 제일 앞에서 필터링 해주는 곳
  • SQL Injection, CSRF 공격 등은 어떤 요청이든 차단되야하기 때문에 여기서 많이 처리해줬었습니다.

인터셉터

  • 스프링에서 제공하는 공통처리 기능
  • HandlerMapping을 통해 어떤 컨트롤러로 갈지 이미 결정이 된 요청에 대해서 처리해줌
  • 실제 매핑된 Handler 정보 확인이 가능(어떤 것이 실제 내 요청을 처리하는지도 확인 가능)
  • 조금 더 상세한 조건식과 세부적인 스펙(pre, post, after)를 통해 구체적인 시점에 구체적인 동작 가능
  • AOP와 비교한다면 AOP는 인터셉터보다 더 구체적인 조건(어노테이션, 파라미터, 주소 등과 같은 자바 코드에서)과
    동작 위치(afterThrowing 등)을 갖음

정리

필터나 인터셉터는 웹에 조금 더 치중되어 있다(웹의 주소나 프로토콜 등으로 필터나 인터셉터를 걸음)

필터는 정말 들어와선 안되는 요청인 것들을 필터링 해주는 기능에 조금 더 치중되어 있습니다.

 

인터셉터는 어떤 핸들러(컨트롤러)로 요청이 가게 될지 결정이 된 상태에서 공통화된 처리를 하는 기능에 치중되어 있습니다.

 

AOP는 URL 주소보다는 실제 어노테이션, 패키지 등등 자바 코드에 관련된 조건식을 통해서 어디에 AOP를 걸지 한정 짓습니다.

 


필터 구현체

외부 -> filter (-> 처리 ->) filter -> 외부

필터와 필터 사이에서 chain을 활용해서 연결해줘야만 처리가 내부(안쪽)으로 들어갈 수 있습니다.

필터, 인터셉터는 여러 개일 수 있으며 필터간에 이어준다고 생각하면 됩니다.

@Slf4j
@Component
public class LogFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request,
                         ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        log.info("Hello LogFilter : " + Thread.currentThread());
        chain.doFilter(request, response);
        log.info("Bye LogFilter : " + Thread.currentThread());
    }
}

위 코드처럼 Component를 통해 등록하는게 아니라

WebConfig라는 이름의 Configuration을 만들어서 Bean으로 등록하는 것이 관례입니다.

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;

@Configuration
public class WebConfig {

    @Bean
    public FilterRegistrationBean loggingFilter() {
        FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(new LogFilter());
        filterRegistrationBean.setOrder(1); // 필터가 다중으로 있을 때 순서 지정
        filterRegistrationBean.addUrlPatterns("/*"); // 전체 URL에 필터 등록
        return filterRegistrationBean;
    }
}

 


인터셉터 구현체

preHandle: 핸들러 처리 전

postHandle: 핸들러(컨트롤러) 처리 후 성공시에만 들어옵니다.

afterCompletion: 핸들러 성공 여부와 관계 없이 Exception이 발생해도 들어오고 성공해도 들어옵니다.

 

@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; // true if the execution chain should proceed with the next interceptor
        // or the handler itself.
        // Else, DispatcherServlet assumes that this interceptor has already dealt
        // with the response itself.
    }

    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        log.info("postHandle LogInterceptor : " + Thread.currentThread());
        // 핸들러 처리 후 생성된 ModelAndView를 가지고 있음
    }

    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler, Exception ex) throws Exception {
        log.info("afterCompletion LogInterceptor : " + Thread.currentThread());

        if (ex != null) {
            log.error("afterCompletion exception : " + ex.getMessage());
        }
    }
}
  • 필터와 동일한 기능을 하는 코드를 작성할 수 있습니다.
  • 다만 더 세밀한 조건식 (include, exclude 등)과 preHandle, postHandle, afterCompletion를 통한 다양한 처리가 가능합니다.
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public FilterRegistrationBean loggingFilter() {
        FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(new LogFilter());
        filterRegistrationBean.setOrder(1); // 필터가 다중으로 있을 때 순서 지정
        filterRegistrationBean.addUrlPatterns("/*"); // 전체 URL에 필터 등록
        return filterRegistrationBean;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LogInterceptor())
                .order(1)
                .addPathPatterns("/**")
                .excludePathPatterns("/css/*", "/images/*");
    }
}

WebMvcConfigurer를 구현하여 인터셉터를 추가할 수 있습니다.

'Develop > Spring' 카테고리의 다른 글

Spring Test (JUnit, Mockito, Spring Boot)  (0) 2022.11.21
Spring Exception  (0) 2022.11.19
Spring MVC  (0) 2022.11.17
(작성 중) Spring web.xml  (0) 2022.11.16
Spring SpEL  (0) 2022.11.16