스프링 웹 MVC-08.핸들러 인터셉터


핸들러 인터셉터 1부: 개념

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.html#addInterceptors-org.springframework.web.servlet.config.annotation.InterceptorRegistry-

HandlerInterceptor

  • 핸들러 맵핑에 설정할 수 있는 인터셉터
  • 핸들러를 실행하기 전, 후(아직 랜더링 전) 그리고 완료(랜더링까지 끝난 이후) 시점에 부가 작업을 하고 싶은 경우에 사용할 수 있다.
  • 여러 핸들러에서 반복적으로 사용하는 코드를 줄이고 싶을 때 사용할 수 있다.
    • 로깅, 인증 체크, Locale 변경 등…

boolean preHandle(request, response, handler)

  • 핸들러 실행하기 전에 호출 됨
  • “핸들러”에 대한 정보를 사용할 수 있기 때문에 서블릿 필터에 비해 보다 세밀한 로직을 구현할 수 있다.
  • 리턴값으로 계속 다음 인터셉터 또는 핸들러로 요청,응답을 전달할지(true) 응답 처리가 이곳에서 끝났는지(false) 알린다.

void postHandle(request, response, modelAndView)

  • 핸들러 실행이 끝나고 아직 뷰를 랜더링 하기 이전에 호출 됨
  • “뷰”에 전달할 추가적이거나 여러 핸들러에 공통적인 모델 정보를 담는데 사용할 수도 있다.
  • 이 메소드는 인터셉터 역순으로 호출된다.
  • 비동기적인 요청 처리 시에는 호출되지 않는다.

void afterCompletion(request, response, handler, ex)

  • 요청 처리가 완전히 끝난 뒤(뷰 랜더링 끝난 뒤)에 호출 됨
  • preHandler에서 true를 리턴한 경우에만 호출 됨
  • 이 메소드는 인터셉터 역순으로 호출된다.
  • 비동기적인 요청 처리 시에는 호출되지 않는다.

vs 서블릿 필터

  • 서블릿 보다 구체적인 처리가 가능하다.
  • 서블릿은 보다 일반적인 용도의 기능을 구현하는데 사용하는게 좋다.

참고:

  • https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/HandlerInterceptor.html
  • https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/AsyncHandlerInterceptor.html
  • http://forum.spring.io/forum/spring-projects/web/20146-what-is-the-difference-between-using-a-filter-and-interceptor (스프링 개발자 Mark Fisher의 서블릿 필터와의 차이점에 대한 답변 참고)

핸들러 인터셉터 2부: 구현

핸들러 인터셉터 구현하기

public class GreetingInterceptor implements HandlerInterceptor {

   @Override
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       System.out.println("preHandle 1");
       return true;
   }

   @Override
   public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
       System.out.println("postHandle 1");
   }

   @Override
   public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
       System.out.println("afterCompletion 1");
   }
}

AnotherInterceptor 는 똑같은데 2로 구현시

핸들러 인터셉터 등록하기

@Configuration
public class WebConfig implements WebMvcConfigurer {

   @Override
   public void addInterceptors(InterceptorRegistry registry) {
       registry.addInterceptor(new GreetingInterceptor()).order(-1); // 순서지정, 낮은게 빨리 동작, 보통 미지정시 순서대로
       registry.addInterceptor(new AnotherInterceptor())
               .addPathPatterns("/jaeuk") // 패턴 정의 가능 /jaeuk/*..
               .order(0);
   }
}
  • 특정 패턴에 해당하는 요청에만 적용할 수도 있다. (addPathPatterns)
  • 순서를 지정할 수 있다. (order)
  • preHandle만 오더순으로 동작하고, postHandle와 afterCompletion는 역순으로 동작한다.

ex.

// preHandle 1
// preHandle 2
// 요청 처리
// postHandler 2 (역순)
// postHandler 1
// 뷰 렌더링
// afterCompletion 2 (역순) - 비동기 호출일때는 실행안됨.(다른게 실행됨. 추후 포스팅)
// afterCompletion 1





© 2019. by jaeuk