목차
Interceptor
스프링 Interceptor 는 Handler(Controller) 호출 전, 후에 사용자 요청 및 응답을 가로채 특정 로직을 수행하는 역할을 한다.
- DispatcherServlet 이후에 동작한다.
- 스프링 Filter 처럼 Request, Response 객체를 다른 객체로 변경하는 것이 불가능 하다.
- Interceptor 는 Request, Response 객체를 넘겨주는 방식으로 진행하지 않고, boolean 값을 반환하는 형태로 로직 수행
Interceptor 인터페이스
- preHandle
- Handler 호출 전에 실행된다.
- HttpServletRequest 객체를 이용해
- preHandle 이 true 를 반환하면 다음으로 진행하고, false 면 진행하지 않는다.
- postHandle
- afterCompletion
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 { } }
|
Interceptor 예외
Handler(Controller) 실행 중간에 예외가 발생하게 되면 postHandler 는 호출되지 않고, 던져진 예외는 afterCompletion 에 전달된다.
- preHandler 의 경우 Handler 수행 전에 실행되므로 Handler 예외와는 상관이 없다.
- postHandler 의 경우 Handler 예외 발생시 로직이 수행되지 않으므로 예외 발생 상황과 관계없이 Handler 실행 후 작업을 진행하고 싶으면 afterCompletion 메소드를 이용하도록 한다.
- afterCompletion 에 전달된 예외는 로직을 수행한 후 Filter 에도 전달된다.
요청 로그 남기기
@Slf4j public class LogInterceptor implements HandlerInterceptor {
public static final String LOGIN_ID = "loginId";
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String requestURI = request.getRequestURI(); String uuid = UUID.randomUUID().toString();
request.setAttribute(LOGIN_ID, uuid);
if(handler instanceof HandlerMethod){ HandlerMethod hm = (HandlerMethod) handler; }
log.info("REQUEST [{}][{}][{}]", uuid, requestURI, handler);
return true; }
@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { log.info("postHandle [{}]", modelAndView); }
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { String requestURI = request.getRequestURI(); String loginId = (String) request.getAttribute(LOGIN_ID);
log.info("RESPONSE [{}][{}][{}]", loginId, requestURI, handler);
if(ex != null){ log.error("afterCompletion error!!", ex); } } }
|
Interceptor 등록하기
스프링 MVC 설정을 위한 WebMvcConfigurer 인터페이스는 Interceptor 를 등록하기 위한 addInterceptors 메소드를 제공한다. InterceptorRegistry 객체에 새로 만든 Interceptor 와 설정 정보를 넣어주면 적용된다.
@Configuration public class WebConfig implements WebMvcConfigurer {
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LogInterceptor()) .order(1) .addPathPatterns("/**") .excludePathPatterns("/css/**", "/*.ico", "/error"); } }
|
로그인 Check Interceptor 작성하기
@Slf4j public class LoginCheckInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
log.info("인증 체크 인터셉터 실행 {}", requestURI);
HttpSession httpSession = request.getSession(); if(httpSession == null || httpSession.getAttribute(SessionConst.LOGIN_MEMBER) == null){ log.info("미 인증 사용자 요청"); response.sendRedirect("/login?redirectURL="+requestURI);
return false; }
return true; } }
|
Interceptor 등록하기
@Configuration public class WebConfig implements WebMvcConfigurer {
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LogInterceptor()) .order(1) .addPathPatterns("/**") .excludePathPatterns("/css/**", "/*.ico", "/error");
registry.addInterceptor(new LoginCheckInterceptor()) .order(2) .addPathPatterns("/**") .excludePathPatterns("/", "/members/add", "/login", "/logout", "/css/**", "/*.ico", "/error"); } }
|