인터셉터

JIWOO YUN·2024년 3월 8일
0

SpringMVC2

목록 보기
21/26

스프링 인터셉터

  • 스프링 MVC 가 제공한다.
  • 서블릿 필터와 같이 웹과 관련된 공통 사항 관심 사항을 효과적으로 해결할 수 있는 기술.

스프링 인터셉터의 흐름

Http 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러
  • 디스패처 서블릿과 컨트롤러 사이에서 컨트롤러 호출 직전에 호출됨.
  • 스프링 MVC 가 제공하는 기능이기 때문에 디스패처 서블릿 이후에 등장하게 되는 것.

스프링 인터셉터 제한

Http 요청 -> WAS -> 필터 -> 서블릿 -> 인터셉터(적절하지 요청인 경우, 컨트롤러 호출 X)
  • 필터와 마찬가지로 적절하지 요청인 경우에 컨트롤러를 호출하지 않는다.

인터셉터 인터페이스에는 3가지 정도가 제공된다.

public interface HandlerInterceptor {
    
    
	default boolean preHandle(HttpServletRequest request, HttpServletResponse
response,Object handler) throws Exception {}
    
	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 {}
}
  • preHandle (컨트롤러 호출전)
    • 컨트롤러가 호출 전에 호출된다. (핸들러 어댑터 호출 전에 호출)
    • 응답 값이 true 이면 다음 진행, false 이면 더는 진행하지않음.
      • false 인경우 나머지 인터셉터와 핸들러 어댑터도 호출되지않음.
  • PostHandle(컨트롤러 호출 후)
    • 컨트롤러 호출 후에 호출
    • 컨트롤러에서 예외 발생하면 호출되지 않는다.
  • afterCompletion(요청 완료 이후)
    • 뷰가 렌더링 후에 호출된다.
    • 항상 호출이된다.
      • 컨트롤러에서 예외가 발생시 postHandler가 호출되지 않으므로 예외와 무관하게 공통 처리를 할려면 afterCompletion을 사용해야한다.

인터셉터의 요청로그 남기기

LogInterCeptor

@Slf4j
public class LogInterceptor implements HandlerInterceptor {

    public static final String LOG_ID = "logId";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String requestURI = request.getRequestURI();

        String uuid = UUID.randomUUID().toString();

        request.setAttribute(LOG_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 logId =(String) request.getAttribute(LOG_ID);

        log.info("RESPONSE [{}][{}]", logId, requestURI);
        if(ex != null){
            log.error("afterCompletion error !!",ex);
        }
    }
}

webConfig 등록

@Configuration
public class WebConfig implements WebMvcConfigurer {

//    @Bean
//    public FilterRegistrationBean logFilter(){
//        FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
//        filterFilterRegistrationBean.setFilter(new LogFilter());
//        filterFilterRegistrationBean.setOrder(1);
//        filterFilterRegistrationBean.addUrlPatterns("/*");
//
//        return filterFilterRegistrationBean;
//    }

    @Bean
    public FilterRegistrationBean loginCheckFilter(){
        FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();

        filterRegistrationBean.setFilter(new LoginCheckFilter());
        filterRegistrationBean.setOrder(2);
        filterRegistrationBean.addUrlPatterns("/*");
        return filterRegistrationBean;
    }

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

WebMvcConfigurer가 제공하는 addInterCeptors 를 사용해서 인터셉터를 등록할 수 있다.

  • 필터와 다르게 매우 정밀하게 URL 패턴을 지정할 수있음.
    • addPathPatterns("/**") : 적용할 URL 패턴 지정
    • .excludePathPatterns("/css/*","/.ico","/error") : 제외할 패턴을 지정

인증 체크를 통해서 로그인 하지 않으면 접근 못하게 막기.

LoginCheckInterceptor

@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 session = request.getSession(false);

        if(session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null){
            log.info("미인증 사용자 요청");

            response.sendRedirect("/login?redirectURL=" + requestURI);
            return false;
        }

        return true;

    }
}
  • 인증이기 때문에 호출전에만 호출하면되기 때문에 preHandler만 구현하면 된다.

Webconfig에 추가하기.

@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");
}

전에 모든 로그 요청하는 인터셉터밑에 또 추가로 진행하면된다.

  • 기본적으로 모든 경로를 인터셉터로 적용하지만 밑의 exclude를 통해서 인증이 필요없는 부분을 빼준다.

확실히 서블릿 필터를 쓴것보다는 편리하게 사용이 가능한 것을 알 수 있다.

profile
열심히하자

0개의 댓글