1. 程式人生 > >springMVC框架--springMVC攔截器原理(五)

springMVC框架--springMVC攔截器原理(五)

一、     SpringMVC攔截器實現原理

使用者請求到DispatherServlet中,DispatherServlet呼叫HandlerMapping查詢Handler,HandlerMapping返回一個攔截器鏈(HandlerExecutionChain),springmvc中的攔截器是通過HandlerMapping發起的。

         在企業開發,使用攔截器實現使用者認證(使用者登陸後進行身份校驗攔截),使用者許可權攔截和方法效能監控等。


二、     springMVC攔截器的實現方式

第一種方式是要定義的Interceptor類要實現了Spring的HandlerInterceptor

介面

第二種方式是繼承實現了HandlerInterceptor介面的類,比如Spring已經提供的實現了HandlerInterceptor介面的抽象類HandlerInterceptorAdapter

三、     HandlerInterceptor介面的方法說明

HandlerInterceptor介面中定義了三個方法,我們就是通過這三個方法來對使用者的請求進行攔截處理的。

  preHandle(): 這個方法在業務處理器處理請求之前被呼叫,SpringMVC 中的Interceptor是鏈式呼叫的,在一個應用中或者說是在一個請求中可以同時存在多個Interceptor。每個Interceptor 的呼叫會依據它的宣告順序依次執行,而且最先執行的都是Interceptor中的preHandle 方法,所以可以在這個方法中進行一些前置初始化操作或者是對當前請求的一個預處理,也可以在這個方法中進行一些判斷來決定請求是否要繼續進行下去。該方法的返回值是布林值Boolean 型別的,當它返回為false 時,表示請求結束,後續的Interceptor 和Controller都不會再執行;當返回值為true 時就會繼續呼叫下一個Interceptor 的preHandle 方法,如果已經是最後一個Interceptor 的時候就會是呼叫當前請求的Controller 方法。

     postHandle():這個方法在當前請求進行處理之後,也就是Controller方法呼叫之後執行,但是它會在DispatcherServlet 進行檢視返回渲染之前被呼叫,所以我們可以在這個方法中對Controller處理之後的ModelAndView 物件進行操作。postHandle 方法被呼叫的方向跟preHandle 是相反的,也就是說先宣告的Interceptor postHandle 方法反而會後執行。

    afterCompletion():該方法也是需要當前對應的Interceptor 的preHandle 方法的返回值為true 時才會執行。顧名思義,該方法將在整個請求結束之後,也就是在DispatcherServlet渲染了對應的檢視之後執行。這個方法的主要作用是用於進行資源清理工作的。afterCompletion

方法被呼叫的方向和perHandle也是相反的,先宣告的InterceptorafterCompletion方法後執行。

四、     攔截器的應用(使用者登入認證)

自定義一個LoginInteceptor實現HandlerInteceptor介面

public classLoginInterceptor implements HandlerInterceptor {
 
   //在執行Controller方法之前來執行的
   //用於使用者認證校驗、使用者許可權校驗
   @Override
   public booleanpreHandle(HttpServletRequest request,
         HttpServletResponseresponse, Object handler) throws Exception {
     
      //得到請求的url
      Stringurl = request.getRequestURI();
     
      //判斷是否是公開地址
      //實際開發中需要公開地址配置在配置檔案中
      if(url.indexOf("login.action")>=0){
         //如果是公開地址則放行
         return true;
      }
      //判斷使用者身份在session中是否存在
      HttpSessionsession = request.getSession();
      Stringusercode = (String) session.getAttribute("usercode");
      //如果使用者身份在session中存在放行
      if(usercode!=null){
         return true;
      }
      //執行到這裡攔截,跳轉到登陸頁面,使用者進行身份認證
      request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
      //如果返回false表示攔截不繼續執行handler,如果返回true表示放行
      return false;
   }
   //在執行Controller方法之後返回modelAndView之前來執行
   //如果需要向頁面提供一些公用的資料或配置一些檢視資訊,使用此方法實現從modelAndView入手
   @Override
   public voidpostHandle(HttpServletRequest request,
         HttpServletResponseresponse, Object handler,
         ModelAndViewmodelAndView) throwsException {
      System.out.println("HandlerInterceptor...postHandle");
   }
   //完成對頁面的渲染之後執行此方法
   //作系統統一異常處理,進行方法執行效能監控,在preHandle中設定一個時間點,在afterCompletion設定一個時間,兩個時間點的差就是執行時長
   //實現系統統一日誌記錄
   @Override
   public voidafterCompletion(HttpServletRequest request,
         HttpServletResponseresponse, Object handler, Exception ex)
         throws Exception {
      System.out.println("HandlerInterceptor...afterCompletion");
   }
}

五、     Springmvc.xml中的配置

<!--攔截器 -->
   <mvc:interceptors>
      <mvc:interceptor>
         <!-- /**可以攔截路徑不管多少層 -->
         <mvc:mapping path="/**" />
         <bean class="cn.itcast.ssm.controller.interceptor.LoginInterceptor"></bean>
      </mvc:interceptor>
   </mvc:interceptors>

六、     測試攔截器

在瀏覽器中輸入訪問其他頁面的地址,瀏覽器自動跳轉到登入頁如: