Spring攔截器


一.應用場景

  權限檢查:如是否已經登錄,或則對某些數據具有增刪改查等權限;

  日志記錄:可以記錄請求信息的日志,以便進行信息監控,信息統計等;

  性能監控:慢日志等。

二.攔截器接口

  1.處理器攔截器(HandlerIntercepto):

public interface HandlerInterceptor {

   /**
     * 預處理回調方法,實現處理器的預處理(如檢查登陸),第三個參數為響應的處理器,自定義Controller
     * 返回值:true表示繼續流程(如調用下一個攔截器或處理器);false表示流程中斷(如登錄檢查失敗),不會繼續調用其他的攔截器或處理器,此時我們需要通過response來產生響應;
   */
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception;

   /**
     * 后處理回調方法,實現處理器的后處理(但在渲染視圖之前),此時我們可以通過modelAndView(模型和視圖對象)對模型數據進行處理或對視圖進行處理,modelAndView也可能為null。
   */
    void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception;

   /**
    * 整個請求處理完畢回調方法,即在視圖渲染完畢時回調,如性能監控中我們可以在此記錄結束時間並輸出消耗時間,還可以進行一些資源清理,類似於try-catch-finally中的finally,但僅調用處理器執行鏈中
   */
    void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception;

}

 

  2.攔截適配器(初始化了HandlerIntercepto的相應方法,不用都實現):

    如果只需要實現三個回調方法中的某些方法,可以繼承該抽象類,該抽象類相當於對HandlerIntercepto進行簡單實現。如記錄日志,需要在程序跑完后,記錄相應的增刪改查,只需實現afterConcurrentHandlingStarted()方法。

    注:該攔截器中多了一個afterConcurrentHandlingStarted()方法,該方法用於處理異步請求,當Controller中有異步請求方法的時候會觸發該方法時,異步請求先支持preHandle、然后執行afterConcurrentHandlingStarted。異步線程完成之后執行preHandle、postHandle、afterCompletion。

public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {

    /**
     * 默認是true
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        return true;
    }

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

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

    /**
     * 不是HandlerInterceptor的接口實現,是AsyncHandlerInterceptor的,AsyncHandlerInterceptor實現了HandlerInterceptor
     */
    @Override
    public void afterConcurrentHandlingStarted(
            HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
    }

}

 三.攔截器運行流程

  1.流程順序:

    1.1攔截器執行順序按照Spring配置文件中定義的順序執行;

    1.2首先按照執行順序執行所有攔截器的preHandle()方法【用於預處理等】,如果遇到返回值是false,則不會執行還未執行的攔截器,而是直接倒序執行afterCompletion()方法,如果為true,則依次執行剩下的攔截器;

    1.3如果所有攔截器的preHandle()方法返回值都為true,則執行相應的控制層接口(controller),如果在該接口中有異常拋出,則和preHandle()方法返回false一樣,不會執行postHandle(),而是直接倒序執行afterCompletion()方法;

    1.4如果接口(controller)中業務邏輯執行完成(頁面還未渲染數據),會倒序執行postHandle()方法,渲染完數據后,然后倒序執行afterCompletton()方法。

  2.運行流程圖:

    2.1正常流程(均執行):

    2.2preHandle返回false:

 

四.相關配置及實現

  1.自定義攔截器類實現:

    1.1是否登錄:

package com.swpu.o2o.interceptor.shopadmin;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.swpu.o2o.entity.PersonInfo;
/**
 * 管理系統攔截器
 * @author ASUS
 *
 */
public class ShopLoginInterceptor extends HandlerInterceptorAdapter{

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        //從session中取出用戶信息
        Object userObj=request.getSession().getAttribute("user");
        if(userObj!=null){
            //若用戶信息不為空則將session里的用戶信息轉換成PersonInfos實體類對象
            PersonInfo user=(PersonInfo)userObj;
            if(user!=null&&user.getUserId()!=null&&user.getUserId()>0&&user.getEnableStatus()==1){
                //若通過驗證則返回true,攔截器返回true,控制層業務執行
                return true;
            }
            
        }
        //若不滿驗證,則直接跳轉到登錄界面
        PrintWriter out=response.getWriter();
        out.println("<html>");
        out.println("<script>");
        out.println("window.open ('" + request.getContextPath()
        + "/local/login?usertype=2','_self')");
        out.println("</script>");
        out.println("<html>");
        return false;
    }
    
}

 

    1.2是否有操作權限:

package com.swpu.o2o.interceptor.shopadmin;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.swpu.o2o.entity.Shop;

public class ShopPermissionInterceptor extends HandlerInterceptorAdapter{
    /**
     * 在控制層執行業務前進行用戶操作權限攔截
     */
    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
        //從session獲取當前選擇的店鋪
        Shop currentShop = (Shop) request.getSession().getAttribute(
                "currentShop");
        @SuppressWarnings("unchecked")
        //從session中獲取當前用戶可操作的d店鋪列表
        List<Shop> shopList = (List<Shop>) request.getSession().getAttribute(
                "shopList");
        //非空判斷
        if (currentShop != null && shopList != null) {
            //遍歷可操作的店鋪列表
            for (Shop shop : shopList) {
                //如果當前店鋪在可操作的列表則返回true,進行接下來操作
                if (shop.getShopId() == currentShop.getShopId()) {
                    return true;
                }
            }
        }
        //不滿足驗證,返回false
        return false;
    }
}

 

 

  2.配置文件:

<!-- 5.權限攔截器 -->
    <mvc:interceptors>
        <!-- 校驗是否登錄了該管理系統的攔截器 -->
        <mvc:interceptor>
            <!-- 定義攔截的路由,shopadmin包下的所有Controller -->
            <mvc:mapping path="/shopadmin/**" />
            <!-- 攔截方法 -->
            <bean class="com.swpu.o2o.interceptor.shopadmin.ShopLoginInterceptor"
                id="ShopInterceptor" />
        </mvc:interceptor>
        <!-- 校驗是否對該店鋪有操作權限的攔截器 -->
        <mvc:interceptor>
            <!-- 需要攔截的接口 -->
            <mvc:mapping path="/shopadmin/**" />
            <!-- shoplist page -->
            <!-- 排除該包下的某些接口不攔截 -->
            <mvc:exclude-mapping path="/shopadmin/shoplist" />
            <mvc:exclude-mapping path="/shopadmin/getshoplist" />
            <!-- shopmanage page -->
            <mvc:exclude-mapping path="/shopadmin/shopmanagement" />
            <mvc:exclude-mapping path="/shopadmin/getshopmanagementinfo" />
            <!-- shopregister page -->
            <mvc:exclude-mapping path="/shopadmin/getshopinitinfo" />
            <mvc:exclude-mapping path="/shopadmin/shopoperation" />
            <mvc:exclude-mapping path="/shop/registershop" />
            <bean class="com.swpu.o2o.interceptor.shopadmin.ShopPermissionInterceptor"
                id="ShopPermissionInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM