SpringMVC處理器攔截器 Interceptor


攔截器概念

  Java 里的攔截器是動態攔截action調用的對象。它提供了一種機制可以使開發者可以定義在一個action執行的前后執行的代碼,也可以在一個action執行前阻止其執行,同時也提供了一種可以提取action中可重用部分的方式。在 AOP(Aspect-Oriented Programming,面向切面編程)中攔截器用於在某個方法(包括構造器)或字段被訪問之前進行攔截,然后在之前或之后加入某些操作。特別地,現階段 Spring 自身僅支持基於方法的攔截操作!如果基於方法的攔截操作不能滿足需求,可以使用 AspectJ 與 Spring 進行集成,以實現更細粒度或更多方面的攔截操作。

常見應用場景 

  1、日志記錄:記錄請求信息的日志,以便進行信息監控、信息統計、計算PV(Page View)等。

  2、權限檢查:如登錄檢測,進入處理器檢測檢測是否登錄,如果沒有直接返回到登錄頁面;

  3、性能監控:有時候系統在某段時間莫名其妙的慢,可以通過攔截器在進入處理器之前記錄開始時間,在處理完后記錄結束時間,從而得到該請求的處理時間(如果有反向代理,如apache可以自動記錄);

  4、通用行為:讀取cookie得到用戶信息並將用戶對象放入請求,從而方便后續流程使用,還有如提取Locale、Theme信息等,只要是多個處理器都需要的即可使用攔截器實現。

  5、OpenSessionInView:如Hibernate,在進入處理器打開Session,在完成后關閉Session。

  …………本質也是AOP(面向切面編程),也就是說符合橫切關注點的所有功能都可以放入攔截器實現。

攔截器接口( 通過實現HandlerInterceptor接口, 一般通過繼承HandlerInterceptorAdapter抽象類實現。)

package org.springframework.web.servlet;  
public interface HandlerInterceptor {  
    boolean preHandle(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler)   
            throws Exception;  
  
    void postHandle(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler, ModelAndView modelAndView)   
            throws Exception;  
  
    void afterCompletion(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler, Exception ex)  
            throws Exception;  
}   

preHandle:預處理回調方法,實現處理器的預處理(如登錄檢查),第三個參數為響應的處理器(如我們上一章的Controller實現);

       返回值:true表示繼續流程(如調用下一個攔截器或處理器);

                   false表示流程中斷(如登錄檢查失敗),不會繼續調用其他的攔截器或處理器,此時我們需要通過response來產生響應;

postHandle:后處理回調方法,實現處理器的后處理(但在渲染視圖之前),此時我們可以通過modelAndView(模型和視圖對象)對模型數據進行處理或對視圖進行處理,modelAndView也可能為null。

afterCompletion:整個請求處理完畢回調方法,即在視圖渲染完畢時回調,如性能監控中我們可以在此記錄結束時間並輸出消耗時間,還可以進行一些資源清理,類似於try-catch-finally中的finally,但僅調用處理器執行鏈中preHandle返回true的攔截器的afterCompletion。


 實戰代碼:

工程結構

springmvc.xml spring的配置

 定義三個攔截器 AllInterceptor 是全局攔截器, Interceptor1、 Interceptor2是獨立的攔截器使用

 

package com.spring.interceptor;

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

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

public class AllInterceptor extends HandlerInterceptorAdapter{
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
        System.out.println("===========AllInterceptor preHandle");  
        return true;  
    }  
    @Override  
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {  
        System.out.println("===========AllInterceptor postHandle");  
    }  
    @Override  
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {  
        System.out.println("===========AllInterceptor afterCompletion");  
    }  
}
package com.spring.interceptor;

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

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

public class Interceptor1 extends HandlerInterceptorAdapter{
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
        System.out.println("===========Interceptor1 preHandle");  
        return true;  
    }  
    @Override  
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {  
        System.out.println("===========Interceptor1 postHandle");  
    }  
    @Override  
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {  
        System.out.println("===========Interceptor1 afterCompletion");  
    } 
}
package com.spring.interceptor;

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

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

public class Interceptor2 extends HandlerInterceptorAdapter{
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
        System.out.println("===========Interceptor2 preHandle");  
        return true;  
    }  
    @Override  
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {  
        System.out.println("===========Interceptor2 postHandle");  
    }  
    @Override  
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {  
        System.out.println("===========Interceptor2 afterCompletion");  
    } 
}

Controller層  TestController1.java

package com.spring.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("interceptor")
public class TestController1 {

    @RequestMapping("test1")
    public void test1() {
        System.out.println("Controller test1 !");
    }
    
    @RequestMapping("test2")
    public void test2() {
        System.out.println("Controller test2 !");
    }
}

spring相關配置

<!-- 掃描含有@Controller注解 -->
    <context:component-scan base-package="com.spring.controller">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
<!-- 使用mvc:interceptors標簽來聲明需要加入到SpringMVC攔截器鏈中的攔截器 -->
    <mvc:interceptors>  
        <!-- 使用bean定義一個Interceptor,直接定義在mvc:interceptors根下面的Interceptor將攔截所有的請求 -->  
        <bean class="com.spring.interceptor.AllInterceptor"/>  
        <mvc:interceptor>  
            <mvc:mapping path="/interceptor/test1"/>  
            <!-- 定義在mvc:interceptor下面的表示是對特定的請求才進行攔截的 -->  
            <bean class="com.spring.interceptor.Interceptor1"/>  
        </mvc:interceptor>  
        <mvc:interceptor>  
            <mvc:mapping path="/interceptor/test2"/>  
            <bean class="com.spring.interceptor.Interceptor2"/>  
        </mvc:interceptor> 
    </mvc:interceptors>  

測試結果:

url:  http://localhost:8080/dynamicdatasource/interceptor/test1

 

url:  http://localhost:8080/dynamicdatasource/interceptor/test2

 

另外 對已攔截器的配置,有時候需要是對全部請求url進行攔截,有時候對一些url不進行攔截,可以采用下面幾種方式;

<mvc:interceptors>
        <bean id="allInterceptor" class="com.base.interceptor.AllInterceptor"/>
        <mvc:interceptor>
            <mvc:mapping path="/*/**" />
            <bean id="CommonInterceptor" class="com.base.interceptor.CommonInterceptor"/>
        </mvc:interceptor>   
        <mvc:interceptor>
            <mvc:mapping path="/dical/**"/> //攔截的url
            <mvc:mapping path="/admin/**"/>//攔截的url
            <mvc:exclude-mapping path="/admin/login"/> //不攔截的url
            <mvc:exclude-mapping path="/admin/main"/>//不攔截的url
                <bean id="DicalInterceptor" class="com.base.interceptor.DicalInterceptor"/>
        </mvc:interceptor>

</mvc:interceptors>

或者:

<mvc:interceptors>
         <mvc:interceptor>
             <mvc:mapping path="/**"/>
             <mvc:exclude-mapping path="/bank/modifCode/**"/>
             <mvc:exclude-mapping path="/bank/tialize/**"/>
             <mvc:exclude-mapping path="/bank/**"/>
             <bean class="com.intercr.MthoduestIneptor" />
         </mvc:interceptor>
    </mvc:interceptors>

說明:

  1)mvc:mapping 攔截器路徑配置

  2)mvc:exclude-mapping 攔截器不需要攔截的路徑

 


免責聲明!

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



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