반응형

 

SpringBoot에서 쉽고 빠르게 Interceptor를 적용하는 방법을 알아보겠습니다.

스프링 인터셉터도 서블릿 필터와 같이 웹과 관련된 공통 관심 사항을 효과적으로 해결할 수 있는 기술입니다.

서블릿 필터가 서블릿이 제공하는 기술이라면, 스프링 인터셉터는 스프링 MVC가 제공하는 기술입니다.

둘다 웹과 관련된 공통 관심 사항을 처리하지만, 적용되는 순서와 범위, 그리고 사용방법이 다릅니다.

 

Spring에서 서블릿 필터를 적용하고 싶다면 아래 링크 클릭!

[Spring Filter 적용하기]

인터셉터 흐름

HTTP 요청 -> WAS -> 필터 -> 서블릿(dispatcherservlet) -> 스프링 인터셉터 -> 컨트롤러

인터셉터 특징

 1. 스프링 인터셉터에 URL 패턴을 적용할 수 있는데, 서블릿 URL 패턴과는 다르고, 매우 정밀하게 설정할 수 있습니다.

 2. 서블릿 필터의 경우 단순하게 doFilter() 하나만 제공되지만 인터셉터는 컨트롤러 호출 전(preHandle), 호출 후(postHandle), 요청 완료 이후(afterCompletion)와 같이 단계적으로 잘 세분화 되어 있다.

  ** (예외 발생 시 postHandle은 실행이 안되고, preHandle, afterCompletion만 실행된다.)

 3. 서블릿 필터의 경우 단순히 request , response 만 제공했지만, 인터셉터는 어떤 컨트롤러( handler )가 호출되는지 호출 정보도 받을 수 있다. 그리고 어떤 modelAndView 가 반환되는지 응답 정보도 받을 수 있다.

 

소스 코드

TestInterceptor.java

  - HadlerInterceptor를 구현하면 Spring Interceptor를 사용할 수 있다.

 

package com.bumblebee.dailyspecial.domain.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Slf4j
public class TestInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("preHandle");
        String requestURI = request.getRequestURI();
        log.info(requestURI);
        return true; // return true면 정상 호출, 다음 인터셉터나 컨트롤러 호출한다.
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("afterCompletion");
    }
}

 

위에서 작성한 인터셉터를 등록해줘야 합니다.

WebConfig.java

 

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(new TestInterceptor())
                .order(1) // Interceptor 적용 순서
                // filter와 다르게 매우 정밀하게 url 패턴 적용이 가능하다.
                .addPathPatterns("/**") // 적용될 url 패턴
                .excludePathPatterns("/css/**", "/*.ico", "/error"); //제외될 url 패턴
    }
}

 

TestInterceptor 출력 화면

 

 

 

 ** Interceptor 주의 사항

서블릿 필터의 경우 (init, doFilter, destroy) 메소드에서 공유할 변수를 지역변수로 해결이 가능하지만,

스프링 인터셉터는 호출 시점이 완전히 분리되어 있습니다.

따라서 preHandle 에서 지정한 값을 postHandle , afterCompletion 에서 함께 사용하려면 어딘가에 담아두어야 합니다. TestInterceptor 도 싱글톤 처럼 사용되기 때문에 맴버변수를 사용하면 위험합니다.

따라서 request 에 담아두었다가( request.setAttribute(test, 123) ).

이 값은 afterCompletion 에서 request.getAttribute(test) 로 찾아서 사용하면 됩니다.

 

728x90
반응형
반응형

SpringBoot에서 쉽고 빠르게 Filter를 적용하는 방법을 알아보겠습니다.

FIlter는 서블릿이 지원하는 수문장이다.

 

필터 흐름

HTTP 요청 -> WAS -> 필터 -> 서블릿(Spring에서는 dispatcherservlet) -> 컨트롤러

 

필터 특징

1. 특정 URL 패턴에 적용할 수 있다.(/* 모든 요청 적용)

2. 필터 체인을 이용해서 필터를 자유롭게 추가할 수 있다.

 

소스 코드

TestFilter.java

  - Spring에서 Filter는 Filter interface를 구현하면 사용할 수 있다.

  - Filter interface를 구현하게 되면 init, doFilter, destory 3가지 메소드를 Override 하게 된다.(doFilter 메소드는 반드시 구현되어야 한다.)

 

package com.bumblebee.dailyspecial.domain.filter;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@Slf4j
public class TestFilter implements Filter {


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("TestFilter init");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        
        log.info("TestFilter doFilter");
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        
        log.info(httpRequest.getRequestURI());
        chain.doFilter(request, response); 
        // 이 부분이 가장 중요하다. 
        //다음 필터가 있으면 필터를 호출하고, 필터가 없으면 서블릿을 호출한다. 
        //만약 이 로직을 호출하지 않으면 다음 단계로 진행되지 않는다.
    }

    @Override
    public void destroy() {
        log.info("TestFilter init");
    }
}

 

init(): 필터 초기화 메서드, 서블릿 컨테이너가 생성될 때 호출된다.
doFilter(): HTTP 요청이 올 때 마다 해당 메서드가 호출된다. 필터의 로직을 구현하면 된다.

destroy(): 필터 종료 메서드, 서블릿 컨테이너가 종료될 때 호출된다.

 

위에서 작성한 Filter를 등록해준다.

  - WebMvcConfigurer 구현해서 FilterRegistrationBean으로 필터를 등록해준다.

 

package com.bumblebee.dailyspecial.config;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.Filter;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public FilterRegistrationBean TestFilter() {
        // SpringBoot 에서는 FilterRegistrationBean을 이용해서 필터 설정(was 올릴 때 서블릿 컨테이너 올릴 때 알아서 등록을 해준다.)
        FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(new TestFilter()); // 등록할 필터
        filterRegistrationBean.setOrder(1); // 필터 순서
        filterRegistrationBean.addUrlPatterns("/*"); // 필터 적용할 url 패턴

        return filterRegistrationBean;
    }


}

 

TestFilter 출력 화면

was 기동 후 init 메소드 호출
HTTP 요청 후 doFilter 메소드 호출
was 종료 후 destroy 메서드 호출

 

728x90
반응형

+ Recent posts