ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Intercept
    백엔드/SPRING MVC 2024. 10. 7. 14:47
    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 MVC' 카테고리의 다른 글

    예외처리 (API)  (0) 2024.10.07
    예외처리 (web page)  (0) 2024.10.07
    Servlet Filter  (0) 2024.10.07
    Session 사용법  (0) 2024.10.06
    Cookie 사용법  (0) 2024.10.06
Designed by Tistory.