230621_ Filter와 Interceptor

hoy_·2023년 6월 21일
0

Today, I Learned

목록 보기
23/36

1. 오늘의 일정

  1. Spring 숙련




2. 배운 내용

  • Filter , Interceptor , AOP ...
    • Client의 요청이 Controller로 들어오기 전에 공통 관심사를 기준으로 작업을 처리함으로써 중복 코드를 줄이는 역할을 한다.


  1. Filter
  • 디스패처 서블릿(Dispatcher Servlet)에 요청이 전달되기 전/후에 url 패턴에 맞는 모든 요청에 대해 부가작업을 처리할 수 있는 기능을 제공한다. 디스패처 서블릿은 스프링의 가장 앞단에 존재하는 프론트 컨트롤러이므로, 필터는 스프링 범위 밖에서 처리가 된다.

  • javax.servlet의 Filter 인터페이스를 implements 받아 사용한다.

    • 보유 메서드
      init()
      - 필터 객체를 초기화하고 서비스에 추가, 이후의 작업은 doFilter()에서 이루어짐.

      doFilter()
      - 필터가 본격적으로 할 작업의 내용을 적음. 필터체인으로 연결하여 필터와 매핑된 URL에 요청이 들어올때마다 doFilter()가 호출됨.
      - filterChain은 다음 필터를 가리키고 filterChain.doFilter()는 다음 필터를 호출함. 다음 필터가 없다면 내부적으로 서블릿의 service()를 호출.

      destroy()
      - 필터가 웹 컨테이너에서 삭제될 때 호출함.


  • Filter 사용 예제
@WebFilter(urlPatterns = "/*")
public class PerformanceFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
    					FilterChain filterChain) throws IOException, ServletException {
        // 1. 전처리 작업
        long startTime = System.currentTimeMillis();

        // 2. 서블릿(컨트롤러) 또는 다음 필터
        filterChain.doFilter(request, response);

        // 3. 후처리 작업
        long endTime = System.currentTimeMillis();
        System.out.print("[" + ((HttpServletRequest)request).getRequestURI() + "]");
        System.out.println(" time = " + (endTime - startTime));

        // 관심사의 분리 적용 x
    }
}



  1. Interceptor
  • 디스패처 서블릿이 컨트롤러를 호출하기 전/후에 요청과 응답을 참조하거나 가공할 수 있는 기능을 제공한다. 인터셉터는 웹 컨테이너에서 동작하는 필터와 달리 스프링 컨텍스트에서 동작한다.

  • org.springframework.web.servlet의 HandlerInterceptor 인터페이스를 implements 받아 사용한다.

    • 보유 메서드
      preHandle()
      - 컨트롤러 이전에 처리해야 하는 전처리 작업이나 요청 정보를 가공하고 추가하는 경우에 사용할 수 있음. 반환타입 boolean으로 반환값이 true면 다음 단계로 진행, false라면 작업을 중단.

      postHandle()
      - 컨트롤러 이후에 처리해야 하는 후처리 작업이 있을 때 사용할 수 있음.

      afterCompletion()
      - 모든 뷰에서 최종 결과를 생성하는 등 작업이 완료된 후에 실행됨. 요청 처리 중에 사용한 리소스를 반환할 때 사용하기에 적합.


  • InterCeptor 사용 예제
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new PerformanceInterceptor())
                .addPathPatterns("/**") // 인터셉터 적용 대상
                .excludePathPatterns("/css/**", "/js/**"); // 인터셉터 적용 제외대상
    }
}

-----------------

@Component
public class PerformanceInterceptor implements HandlerInterceptor {
//    long startTime; // 1. iv 변수로 저장하거나 (다른 쓰레드에서 값 덮어쓸 수 있음 주의)
//    long endTime;

    @Override
    public boolean preHandle(HttpServletRequest request, 
    					HttpServletResponse response, Object handler) throws Exception {
        long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime); // 2. request 객체에 저장하여 사용

        // handler - 요청하고 연결된 컨트롤러의 메서드
        HandlerMethod method = (HandlerMethod) handler;
        System.out.println("method.getMethod() = " + method.getMethod()); // URL과 연결된 메서드
        System.out.println("method.getBean() = " + method.getBean()); // 메서드가 포함된 컨트롤러

        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, 
    					Object handler, ModelAndView modelAndView) throws Exception {
        long startTime = (long)request.getAttribute("startTime");
        long endTime = System.currentTimeMillis();
        System.out.print("[" + ((HttpServletRequest)request).getRequestURI() + "]");
        System.out.println(" time = " + (endTime - startTime));

        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }
}



profile
배우는 사람

0개의 댓글