본문 바로가기
Spring Framework/SPRING MVC

Spring Intercept

by 거북이의 기술블로그 2024. 10. 7.
spring mvc Intercept...

 

Intercept 란?

Servlet 필터와 유사한 역할을 하는 기능.
다만, 차이점이 있다면 Spring MVC 에서 제공하는 기능이며, Servlet Filter 이후에 동작하는 차이점이 존재
  • Intercept의 특징은 Servlet Filter에서 제공하는 doFilter() 메서드 한개와 다르게 순서에 따라 3개의 메서드가 존재

 

Intercept 흐름

HTTP 요청 -> WAS -> Filter -> Servlet -> Intercept -> Controller
  • Servlet Filter가 Intercept 보다 먼저 호출됨
  • 중복 처리 되지 않도록 주의하며 설계해야함

 

Intercept 인터페이스

public interface HandlerInterceptor {
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}
  • preHandler() : Controller 호출 전에 호출 ( boolean 반환값으로, true 이면 다음으로 진행되고 false 이면 다음으로 넘어가지 않음 )
  • postHandler() : Controller 호출 후에 호출 ( Controller에서 예외가 발생하면 postHandler() 메서드는 호출되지 않음 ) 
  • afterCompletion() : view 렌더링 이후 호출 ( Controller에서 예외가 발생하더라도 afterCompletion() 메서드는 호출됨 )
    • afterCompletion() 메서드의 경우 Controller에서 예외 발생시 예외 정보를 반환할 수 있음

 

Intercept 구현

  • 주의할점
    • MyInterceptor 클래스의 경우 bean에 등록되므로, 싱글톤으로 진행되게 된다 (멤버변수를 주의하여 사용해야함)
      • uuid를 활용하여 request에 요청별로 구분하고, 가져다 사용할 수 있도록 진행
      • 이렇게 불편하게(?) 사용한 이유는 , preHandler() / postHandle() / afterCompletion() 호출 시기가 다 다르기 때문에 이런식으로 구현하게 됨
    • Controller 핸들러 종류
      • @RequestMapping (동적 처리)
        • HandlerMethod인 경우, 추가적인 정보가 존재하기에 필터링하여 사용할 수 있다. 
        •  
      • 정적리소스 처리 (/resources/static)
        • ResourceHttpRequestHandler인 경우, 정적인 처리를 위한 핸들러이므로 이것에 대한 특정 정보는 따로 처리를 해줘야한다.
    • 공통적인 정상처리 및 예외처리를 하기 위해서는 afterCompletion() 메서드를 사용
      • Controller에서 예외 발생시, postHandle()은 호출이 되지 않기에 공통적인 예외처리는 afterCompletion() 메서드를 이용
@Slf4j
public class MyInterceptor implements HandlerInterceptor{
    
    private static final String ID = "specify Id";
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object Handler) throws Exception{
        
        String requestURI = request.getRequestUri();
        
        String uuid = UUID.randomUUID().toString();
        request.setAttribute(ID, uuid);
        
        if ( handler instaceOf HandlerMethod ){
            HandlerMethod hm = (HandlerMethod) handler;        
        }
        
        return true;
    }
    
    
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("postHandle [{}]", modelAndView); // Controller 예외시 호출 되지 않음
    }
    
    
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        
        String requestURI = request.getRequestURI();
        String logId = request.getAttribute(ID);
        
        log.info("RESPONSE {} {}", logId, requestURI);
        
        if ( ex != null ){
            log.error("afterCompletion error!", ex);
        }
    }
}

 

 

 

Intercept 등록 방법

  • addInterceptors() 메서드를 @Override 하여 구현한 Intercept를 등록
  • WebMvcConfigurer의 인터페이스를 이용하여 WebConfig 구성
  • order() 메서드를 이용하여 우선순위 설정
  • addPathPatterns() 메서드를 사용하여 적용 범위 설정
  • excludePathPatterns() 메서드를 사용하여 적용하지 않을 범위 설정
@Configuration
public class WebConfig implements WebMvcConfigurer {

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

}

 

 

 

'Spring Framework > SPRING MVC' 카테고리의 다른 글

예외처리 (API)  (0) 2024.10.07
예외처리 (web page)  (0) 2024.10.07
Servlet Filter  (0) 2024.10.07
Session 사용법  (0) 2024.10.06