程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> springmvc學習筆記(20)-攔截器

springmvc學習筆記(20)-攔截器

編輯:JAVA綜合教程

springmvc學習筆記(20)-攔截器


springmvc學習筆記(20)-攔截器


本文主要介紹springmvc中的攔截器,包括攔截器定義和的配置,然後演示了一個鏈式攔截的測試示例,最後通過一個登錄認證的例子展示了攔截器的應用

攔截定義

定義攔截器,實現HandlerInterceptor接口。接口中提供三個方法。

public class HandlerInterceptor1 implements HandlerInterceptor{
    //進入 Handler方法之前執行
    //用於身份認證、身份授權
    //比如身份認證,如果認證通過表示當前用戶沒有登陸,需要此方法攔截不再向下執行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        //return false表示攔截,不向下執行
        //return true表示放行
        return false;
    }

    //進入Handler方法之後,返回modelAndView之前執行
    //應用場景從modelAndView出發:將公用的模型數據(比如菜單導航)在這裡傳到視圖,也可以在這裡統一指定視圖
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    //執行Handler完成執行此方法
    //應用場景:統一異常處理,統一日志處理
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

可以從名稱和參數看出各個接口的順序和作用:

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
參數最少,只有三個 進入 Handler方法之前執行 用於身份認證、身份授權。比如身份認證,如果認證通過表示當前用戶沒有登陸,需要此方法攔截不再向下執行 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception
多了一個modelAndView參數 進入Handler方法之後,返回modelAndView之前執行 應用場景從modelAndView出發:將公用的模型數據(比如菜單導航)在這裡傳到視圖,也可以在這裡統一指定視圖 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception
多了一個Exception的類型的參數 執行Handler完成執行此方法 應用場景:統一異常處理,統一日志處理

攔截器配置

針對HandlerMapping配置

springmvc攔截器針對HandlerMapping進行攔截設置,如果在某個HandlerMapping中配置攔截,經過該HandlerMapping映射成功的handler最終使用該攔截器。

<code class="language-xml hljs "><bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
    <property name="interceptors">
        <list>
            <ref bean="handlerInterceptor1">
            <ref bean="handlerInterceptor2">
        </ref></ref></list>
    </property>
</bean>
    <bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1">
    <bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"></bean></bean></code>

一般不推薦使用。

類似全局的攔截器

springmvc配置類似全局的攔截器,springmvc框架將配置的類似全局的攔截器注入到每個HandlerMapping中。

 

    
    
        
        
        
    
    
        
        
    

攔截測試

測試多個攔截器各個方法執行時機

訪問/items/queryItems.action

1.兩個攔截器都放行
DEBUG [http-apr-8080-exec-1] - DispatcherServlet with name 'springmvc' processing GET request for [/ssm1/items/queryItems.action]
DEBUG [http-apr-8080-exec-1] - Looking up handler method for path /items/queryItems.action
DEBUG [http-apr-8080-exec-1] - Returning handler method [public org.springframework.web.servlet.ModelAndView com.iot.learnssm.firstssm.controller.ItemsController.queryItems(javax.servlet.http.HttpServletRequest,com.iot.learnssm.firstssm.po.ItemsQueryVo) throws java.lang.Exception]
DEBUG [http-apr-8080-exec-1] - Returning cached instance of singleton bean 'itemsController'
DEBUG [http-apr-8080-exec-1] - Last-Modified value for [/ssm1/items/queryItems.action] is: -1
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
DEBUG [http-apr-8080-exec-1] - Fetching JDBC Connection from DataSource
DEBUG [http-apr-8080-exec-1] - Registering transaction synchronization for JDBC Connection
DEBUG [http-apr-8080-exec-1] - Returning JDBC Connection to DataSource
HandlerInterceptor2...postHandle
HandlerInterceptor1...postHandle
DEBUG [http-apr-8080-exec-1] - Rendering view [org.springframework.web.servlet.view.JstlView: name 'items/itemsList'; URL [/WEB-INF/jsp/items/itemsList.jsp]] in DispatcherServlet with name 'springmvc'
DEBUG [http-apr-8080-exec-1] - Added model object 'itemtypes' of type [java.util.HashMap] to request in view with name 'items/itemsList'
DEBUG [http-apr-8080-exec-1] - Added model object 'itemsQueryVo' of type [com.iot.learnssm.firstssm.po.ItemsQueryVo] to request in view with name 'items/itemsList'
DEBUG [http-apr-8080-exec-1] - Added model object 'org.springframework.validation.BindingResult.itemsQueryVo' of type [org.springframework.validation.BeanPropertyBindingResult] to request in view with name 'items/itemsList'
DEBUG [http-apr-8080-exec-1] - Added model object 'itemsList' of type [java.util.ArrayList] to request in view with name 'items/itemsList'
DEBUG [http-apr-8080-exec-1] - Forwarding to resource [/WEB-INF/jsp/items/itemsList.jsp] in InternalResourceView 'items/itemsList'
HandlerInterceptor2...afterCompletion
HandlerInterceptor1...afterCompletion
DEBUG [http-apr-8080-exec-1] - Successfully completed request

總結:preHandle方法按順序執行,postHandle和afterCompletion按攔截器配置的逆向順序執行。

2.攔截器1放行,攔截器2不放行

DEBUG [http-apr-8080-exec-8] - DispatcherServlet with name 'springmvc' processing GET request for [/ssm1/items/queryItems.action]
DEBUG [http-apr-8080-exec-8] - Looking up handler method for path /items/queryItems.action
DEBUG [http-apr-8080-exec-8] - Returning handler method [public org.springframework.web.servlet.ModelAndView com.iot.learnssm.firstssm.controller.ItemsController.queryItems(javax.servlet.http.HttpServletRequest,com.iot.learnssm.firstssm.po.ItemsQueryVo) throws java.lang.Exception]
DEBUG [http-apr-8080-exec-8] - Returning cached instance of singleton bean 'itemsController'
DEBUG [http-apr-8080-exec-8] - Last-Modified value for [/ssm1/items/queryItems.action] is: -1
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor1...afterCompletion
DEBUG [http-apr-8080-exec-8] - Successfully completed request

總結:

攔截器1放行,攔截器2 preHandle才會執行。 攔截器2 preHandle不放行,攔截器2 postHandle和afterCompletion不會執行。 只要有一個攔截器不放行,postHandle不會執行。

3.兩個攔截器都不放

DEBUG [http-apr-8080-exec-9] - DispatcherServlet with name 'springmvc' processing GET request for [/ssm1/items/queryItems.action]
DEBUG [http-apr-8080-exec-9] - Looking up handler method for path /items/queryItems.action
DEBUG [http-apr-8080-exec-9] - Returning handler method [public org.springframework.web.servlet.ModelAndView com.iot.learnssm.firstssm.controller.ItemsController.queryItems(javax.servlet.http.HttpServletRequest,com.iot.learnssm.firstssm.po.ItemsQueryVo) throws java.lang.Exception]
DEBUG [http-apr-8080-exec-9] - Returning cached instance of singleton bean 'itemsController'
DEBUG [http-apr-8080-exec-9] - Last-Modified value for [/ssm1/items/queryItems.action] is: -1
HandlerInterceptor1...preHandle
DEBUG [http-apr-8080-exec-9] - Successfully completed request

總結:

攔截器1 preHandle不放行,postHandle和afterCompletion不會執行。 攔截器1 preHandle不放行,攔截器2不執行。

4.攔截器1不放行,攔截器2放行

DEBUG [http-apr-8080-exec-8] - DispatcherServlet with name 'springmvc' processing GET request for [/ssm1/items/queryItems.action]
DEBUG [http-apr-8080-exec-8] - Looking up handler method for path /items/queryItems.action
DEBUG [http-apr-8080-exec-8] - Returning handler method [public org.springframework.web.servlet.ModelAndView com.iot.learnssm.firstssm.controller.ItemsController.queryItems(javax.servlet.http.HttpServletRequest,com.iot.learnssm.firstssm.po.ItemsQueryVo) throws java.lang.Exception]
DEBUG [http-apr-8080-exec-8] - Returning cached instance of singleton bean 'itemsController'
DEBUG [http-apr-8080-exec-8] - Last-Modified value for [/ssm1/items/queryItems.action] is: -1
HandlerInterceptor1...preHandle
DEBUG [http-apr-8080-exec-8] - Successfully completed request

和兩個攔截器都不行的結果一致,因為攔截器1先執行,沒放行

小結

根據測試結果,對攔截器應用。

比如:統一日志處理攔截器,需要該攔截器preHandle一定要放行,且將它放在攔截器鏈接中第一個位置。

比如:登陸認證攔截器,放在攔截器鏈接中第一個位置。權限校驗攔截器,放在登陸認證攔截器之後。(因為登陸通過後才校驗權限,當然登錄認證攔截器要放在統一日志處理攔截器後面)

攔截器應用(實現登陸認證)

需求

1.用戶請求url 2.攔截器進行攔截校驗
如果請求的url是公開地址(無需登陸即可訪問的url),讓放行 如果用戶session 不存在跳轉到登陸頁面 如果用戶session存在放行,繼續操作。

登陸controller方法

@Controller
public class LoginController {
    // 登陸
    @RequestMapping("/login")
    public String login(HttpSession session, String username, String password)
            throws Exception {

        // 調用service進行用戶身份驗證
        // ...

        // 在session中保存用戶身份信息
        session.setAttribute("username", username);
        // 重定向到商品列表頁面
        return "redirect:/items/queryItems.action";
    }

    // 退出
    @RequestMapping("/logout")
    public String logout(HttpSession session) throws Exception {

        // 清除session
        session.invalidate();

        // 重定向到商品列表頁面
        return "redirect:/items/queryItems.action";
    }
}

登陸認證攔截實現

代碼實現
/**
 * Created by brian on 2016/3/8.
 * 登陸認證攔截器
 */

public class LoginInterceptor implements HandlerInterceptor {


    //進入 Handler方法之前執行
    //用於身份認證、身份授權
    //比如身份認證,如果認證通過表示當前用戶沒有登陸,需要此方法攔截不再向下執行
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws Exception {

        //獲取請求的url
        String url = request.getRequestURI();
        //判斷url是否是公開 地址(實際使用時將公開 地址配置配置文件中)
        //這裡公開地址是登陸提交的地址
        if(url.indexOf("login.action")>=0){
            //如果進行登陸提交,放行
            return true;
        }

        //判斷session
        HttpSession session  = request.getSession();
        //從session中取出用戶身份信息
        String username = (String) session.getAttribute("username");

        if(username != null){
            //身份存在,放行
            return true;
        }

        //執行這裡表示用戶身份需要認證,跳轉登陸頁面
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);

        //return false表示攔截,不向下執行
        //return true表示放行
        return false;
    }

    //進入Handler方法之後,返回modelAndView之前執行
    //應用場景從modelAndView出發:將公用的模型數據(比如菜單導航)在這裡傳到視圖,也可以在這裡統一指定視圖
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {

        System.out.println("LoginInterceptor...postHandle");

    }

    //執行Handler完成執行此方法
    //應用場景:統一異常處理,統一日志處理
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response, Object handler, Exception ex)
            throws Exception {

        System.out.println("LoginInterceptor...afterCompletion");
    }

}
攔截器配置


    
    
    
        
        
    

    ...省略

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved