Spring MVC filter, intercepter

공부한것 다 기록해·2023년 8월 9일
0

필터와 인터셉터의 차이

필터

스프링 외부의 서블릿에서 제공하는 공통처리 기능
스프링 내로 요청이 들어오기 전스프링의 요청이 나갈 때 처리 가능
조금 더 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/*"); // 정적 파일 제거
    }
}

0개의 댓글