반응형

인터셉터는 필터와 유사한 동작을 한다. 요청이 controller 에 전달되고 또는 나가는 시점에 요청, 또는 응답을 가로채어 원하는 작업을 수행해줄 수 있다.

 인터셉터에서 사용할 수 있는 세 가지 메소드는 preHandler,  postHandle,  afterCompletion 이다.

preHandle() 메소드는 요청이 controller에서 들어가기 전, poastHandle()은 요청이 controller에 의해 처리되고, 뷰로 보내지기 전,

afterCompletion() 메소드는 뷰까지 보여지고 난 후, 필요한 작업을 수행할 수 있다. 마치 AOP와 조금 유사한 모습을 보이고 있다.


- preHandle : 클라이언트의 요청을 컨트롤러에 전달하기 전에 호출됨. false를 리턴하면 다음 내용은 실행하지 않는다.
- postHandle : 클라이언트의 요청을 처리한 뒤에 호출됨. 컨트롤러에서 예외가 발생되면 실행하지 않는다.
- afterCompletion : 클라이언트 요청 처리뒤 클리이언트에 뷰를 통해 응답을 전송한뒤 실행 됨. 뷰를 생설항때 예외가 발생해도 실행된다
 

아래는 urlHandlerMapping에 인터셉터를 인젝션해주고 있다. 이 맵핑이 정의하는 url로 들어오는 요청은 인터셉터에 의해 가로채진다.

  1. <!-- Member : 로그인한 사람 허용 -->
     <bean id="memberSecureUrlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
         <property name="interceptors">
             <list>
              <ref bean="loginCheckInterceptor"/>
             </list>
         </property>
         <property name="urlMap">
             <map>
              <entry key="/member/edit.do" value-ref="memberSimpleFormController"/>
              <entry key="/member/logout.do" value-ref="memberMultiActionController"/>
          </map>
         </property>
     </bean>

 

 아래는 preHandler()  메소드를 사용하여, session을 검사하여 로그인 체크를 하고 있다. 로그인이 되지 않은 요청이면, 요청을 끝내버리고,

로그인 된 요청이면 컨트롤러에게 요청이 전달될 것이다. 인터셉터에서 반환된 요청에 의해 웹브라우저에서는 하얀 화면이 보여질 것이다.

  1. public class LoginCheckInterceptor extends HandlerInterceptorAdapter {
  2.  private String sessionUserIdKey;
       ....

  3.  // 로그인 했는지 체크

     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         HttpSession session = request.getSession(false);
         if (session == null) {
          // 처리를 끝냄 - 컨트롤로 요청이 가지 않음
          return false;
      }

  4.   String userId = (String)session.getAttribute(this.sessionUserIdKey);
         if (userId == null) { 
          return false;
         }
      return true;
     }
     
     
     @Override
     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
     
         super.postHandle(request, response, handler, modelAndView);
     }
     
     
     @Override
     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  5. super.afterCompletion(request, response, handler, ex);

  6.   }
  7. }



Spring MVC - Annotation Base HandlerInterceptor

Spring core에서는 AOP를 이용하여 처리내용의 전, 후에 일괄적으로 적용하고 싶은 처리를 추가할수가 있다. 하지만 AOP는 interface를 구현한 곳에만 사용할 수가 있습니다. 그래서 Spring MVC의 Controller에는 상용할수 없죠 자 그럼 만약 로그인 체크를 해야한다면 모든 Controller에 로그인 체크 로직을 넣어줘야할까?. 아니다! 그럼 상위 Controller를 만들고 여기에 로그인 체크로직을 넣고 모든 Controller가 이를 상속 받아 쓰면 어떨까. 그남아 났군.. 이런 것을 위해 Spring MVC 에서는 HandlerMapping이 HandlerInterceptor를 이용하해서 Controller가 요청하는 처리의 전과, 후후에 원하는 기능을 수행할수 있도록 해준다고한다.  ( 뭐 깊숙한 내용까지 알려면 더 공부를하고, 아니면 그냥 Controller에서도 AOP와 같이 쓸수 있도록 제공해준다고 알자 ) HandlerInterceptor는 세가지 메소드를 정의한다

--*   * This implementation always returns <code>true</code>.   --  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)      throws Exception {   return true;  }

 --*   * This implementation is empty.   --  public void postHandle(    HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)    throws Exception {  }

 --*   * This implementation is empty.   --  public void afterCompletion(    HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)    throws Exception {  }

접기

- preHandle : 클라이언트의 요청을 컨트롤러에 전달하기 전에 호출됨. false를 리턴하면 다음 내용은 실행하지 않는다. - postHandle : 클라이언트의 요청을 처리한 뒤에 호출됨. 컨트롤러에서 예외가 발생되면 실행하지 않는다. - afterCompletion : 클라이언트 요청 처리뒤 클리이언트에 뷰를 통해 응답을 전송한뒤 실행 됨. 뷰를 생설항때 예외가 발생해도 실행된다. Interceptor의 구현 org.springframework.web.servlet.HandlerInterceptor 를 직접 구현해서 클래스를 작성해도 되지만 이러면 세개의 메소드를 모두 구현해야한다. 즉 preHandle 만 필요해도 postHandle과 afterCompletion 두 메소드를 모두 구현해야한다. 이를위해 Spring에는 HandlerInterceptorAdaptor 클래스를 제공한다. 이는 이미 HandlerInterceptor interface를 구현한 클래스로 위의 세개의 메소드를 이미 구현하고 있어 필요한것만 구현해서 사용하면 된다. - Interceptor 구현

public class LoginCheckInterceptor extends HandlerInterceptorAdaptor {     @Override     public boolean preHandle(HttpServletRequest request,                                           HttpServletResponse response,                                           Object handler) throws Exception{          if ( !isLogin() ) {              return false;         }         return true;     } }

- dispatcher-servlet.xml의Interceptor 설정

<bean id="annotationMapper"              class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">     <property name="interceptors">         <list>             <ref bean="userLoginInterceptor"/>         </list>     </property>     <property name="alwaysUseFullPath" value="true"/> </bean> <bean id="userLoginInterceptor" class="com.questionbox.interceptor.UserLoginInterceptor" />

위와 같이 할때는 모든 페이지 URL에서 userLoginInterceptor를 실행하게 된다. 그리고  <list>    <ref bean="userLoginInterceptor"/>     <ref bean="userLoginInterceptor2"/>     <ref bean="userLoginInterceptor3"/> </list> 과 같이 여러 인터페이스를 줄수도 있다.


반응형

+ Recent posts