Joswlv

Interceptor

2016-10-02

Interceptor

ServletFilter와 유사하게 DispatcherServlet이 Controller를 호출하기 전/후에 요청 및 응답을 참조, 가공할 수 있는 일종의 필터 역할

Filter와 다른점은 Filter는 DispatcherServlet보다 먼저 실행되기 때문에 Servlet관련 변수들을 사용할 수 없지만 Interceptor는 DispatcherServlet안에서 실행되기 때문에 Servlet관련 변수들을 사용할 수 있다.

HandlerInterceptor interface

  • preHandler : 컨트롤러 실행 전 호출
  • postHandler : 컨트롤러가 정상적으로 실행된 후 호출 (예외 발생하면 호출되지 않음)
  • afterCompletion : 뷰 렌더링 후 호출 (예외 발생하면 메쏘드 인자로 전달됨)

HandlerInterceptorAdapter class

  • HandlerInterceptor 인터페이스의 모든 메쏘드를 빈(empty) 구현한 클래스

Interceptor 설정 - SpringMVC에서

Login Session을 체크하는 interceptor예를 보면 다음과 같다.

servlet-context에서 다음과 같이 추가를한다.

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/" />

            <mvc:mapping path="/member/*" />

            <mvc:exclude-mapping path="/login" />
            <mvc:exclude-mapping path="/logout" />

            <bean class="com.nhnent.springmvc.interceptor.LoginCheckInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>

그리고 LoginCheckInterceptor클래스를 작성한다.

public class LoginCheckInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();

        Member loginInfo = (Member) session.getAttribute("member");
        if (loginInfo == null) {
            throw new UnAuthorizedException();
        }

        return super.preHandle(request, response, handler);
    }
}

login과정과 logout과정은 interceptor 할 필요가 없기 때문에 exclude를 설정한다.

Interceptor 설정 - Spring Boot에서

HandlerInterceptor 인터페이스를 사용하면 preHandle(), postHandle()afterCompletion()를 모두 오버라이딩을 해야한다. 예를 들면 아래와 같다.

public class LoggingInterceptor implements HandlerInterceptor  {
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
		throws Exception {
		System.out.println("---Before Method Execution---");
		return true;
	}
	@Override
	public void postHandle(	HttpServletRequest request, HttpServletResponse response,
			Object handler, ModelAndView modelAndView) throws Exception {
		System.out.println("---method executed---");
	}
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
			Object handler, Exception ex) throws Exception {
		System.out.println("---Request Completed---");
	}
} 

HandlerInterceptorAdapter를 상속받으면 필요한 메소드만 사용할 수 있다. 예를 들면 아래와 같다.

public class TransactionInterceptor extends HandlerInterceptorAdapter {
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
		throws Exception {
		System.out.println("Got request to save data : name:"+request.getParameter("name"));
		return true;
	}
} 

그리고 Config파일을 만들어 addInterceptor()메소드를 사용하여 앞서 만든 Interceptor java파일들을 추가한다. 예는 아래와 같다.

@Configuration  
@EnableWebMvc   
public class AppConfig extends WebMvcConfigurerAdapter  {  
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
	    registry.addInterceptor(new LoggingInterceptor());
	    registry.addInterceptor(new TransactionInterceptor()).addPathPatterns("/person/save/*");
	}
}

마지막으로 WebApplicationInitializer인터페이스를 사용하는 java파일을 만들어 DispatcherServlet에 앞서 설정한 AppConfig를 Servlet-context로 등록시킨다. 예를들면 아래와 같다.

public class WebAppInitializer implements WebApplicationInitializer {
	public void onStartup(ServletContext servletContext) throws ServletException {  
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();  
        ctx.register(AppConfig.class);  
        ctx.setServletContext(servletContext);    
        Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));  
        dynamic.addMapping("/");  
        dynamic.setLoadOnStartup(1);  
   }  
}

Reference


Comments