1. 程式人生 > >詳述 Spring MVC 框架中攔截器 Interceptor 的使用方法

詳述 Spring MVC 框架中攔截器 Interceptor 的使用方法

1 前言

  昨天新接了一個需要,“攔截 XXX,然後 OOO”,好吧,說白了就是要用攔截器乾點事(實現一個具體的功能)。之前,也在網路上搜了很多關於Interceptor的文章,但感覺內容都大同小異,而且知識點零零散散,不太方便閱讀。因此,正好藉此機會,整理一篇關於攔截器的文章,在此分享給大家,以供大家參考閱讀。

2 攔截器

2.1 概念

  Java 裡的攔截器是動態攔截 action 呼叫的物件。它提供了一種機制可以使開發者可以定義在一個 action 執行的前後執行的程式碼,也可以在一個 action 執行前阻止其執行,同時也提供了一種可以提取 action 中可重用部分的方式。在AOP(Aspect-Oriented Programming,面向切面程式設計)中攔截器用於在某個方法或欄位被訪問之前進行攔截,然後在之前或之後加入某些操作。

2.2 原理

  攔截器 Interceptor 的攔截功能是基於 Java 的動態代理來實現的,具體可以參考博文“ 用 Java 實現攔截器 Interceptor 的攔截功能 ”,也可以通過閱讀 Spring 原始碼來了解更為權威的實現細節。

3 實現方法

  在 Spring 框架之中,咱們要想實現攔截器的功能,主要通過兩種途徑,第一種是實現HandlerInterceptor介面,第二種是實現WebRequestInterceptor介面。接下來,咱們分別詳細的介紹兩者的實現方法。

3.1 HandlerInterceptor 介面

HandlerInterceptor介面中,定義了 3 個方法,分別為preHandle()

postHandle()afterCompletion(),咱們就是通過複寫這 3 個方法來對使用者的請求進行攔截處理的。因此,咱們可以通過直接實現HandlerInterceptor介面來實現攔截器的功能。不過在 Spring 框架之中,其還提供了另外一個介面和一個抽象類,實現了對HandlerInterceptor介面的功能擴充套件,分別為:AsyncHandlerInterceptorHandlerInterceptorAdapter.

對於AsyncHandlerInterceptor介面,其在繼承HandlerInterceptor介面的同時,又聲明瞭一個新的方法afterConcurrentHandlingStarted()

;而HandlerInterceptorAdapter抽象類,則是更進一步,在其繼承AsyncHandlerInterceptor介面的同時,又複寫了preHandle方法。因此,AsyncHandlerInterceptor更像是一個過渡的介面。

在實際應用中,咱們一般都是通過實現HandlerInterceptor介面或者繼承HandlerInterceptorAdapter抽象類,複寫preHandle()postHandle()afterCompletion()這 3 個方法來對使用者的請求進行攔截處理的。下面,咱們就詳細介紹這個 3 個方法。

  • preHandle(HttpServletRequest request, HttpServletResponse response, Object handle)方法,該方法在請求處理之前進行呼叫。SpringMVC 中的 Interceptor 是鏈式呼叫的,在一個應用中或者說是在一個請求中可以同時存在多個 Interceptor 。每個 Interceptor 的呼叫會依據它的宣告順序依次執行,而且最先執行的都是 Interceptor 中的 preHandle 方法,所以可以在這個方法中進行一些前置初始化操作或者是對當前請求做一個預處理,也可以在這個方法中進行一些判斷來決定請求是否要繼續進行下去。該方法的返回值是布林值 Boolean 型別的,當它返回為 false 時,表示請求結束,後續的 Interceptor 和 Controller 都不會再執行;當返回值為 true 時,就會繼續呼叫下一個 Interceptor 的 preHandle 方法,如果已經是最後一個 Interceptor 的時候,就會是呼叫當前請求的 Controller 中的方法。
  • postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView)方法,通過 preHandle 方法的解釋咱們知道這個方法包括後面要說到的 afterCompletion 方法都只能在當前所屬的 Interceptor 的 preHandle 方法的返回值為 true 的時候,才能被呼叫。postHandle 方法在當前請求進行處理之後,也就是在 Controller 中的方法呼叫之後執行,但是它會在 DispatcherServlet 進行檢視返回渲染之前被呼叫,所以咱們可以在這個方法中對 Controller 處理之後的 ModelAndView 物件進行操作。postHandle 方法被呼叫的方向跟 preHandle 是相反的,也就是說,先宣告的 Interceptor 的 postHandle 方法反而會後執行。這和 Struts2 裡面的 Interceptor 的執行過程有點型別,Struts2 裡面的 Interceptor 的執行過程也是鏈式的,只是在 Struts2 裡面需要手動呼叫 ActionInvocation 的 invoke 方法來觸發對下一個 Interceptor 或者是 action 的呼叫,然後每一個 Interceptor 中在 invoke 方法呼叫之前的內容都是按照宣告順序執行的,而 invoke 方法之後的內容就是反向的。
  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex)方法,也是需要當前對應的 Interceptor 的 preHandle 方法的返回值為 true 時才會執行。因此,該方法將在整個請求結束之後,也就是在 DispatcherServlet 渲染了對應的檢視之後執行,這個方法的主要作用是用於進行資源清理的工作。

接下來,咱們在看看以上介面和抽象類的具體程式碼:

HandlerInterceptor 介面:

package org.springframework.web.servlet;

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

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

AsyncHandlerInterceptor 介面:

package org.springframework.web.servlet;

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

public interface AsyncHandlerInterceptor extends HandlerInterceptor {

    void afterConcurrentHandlingStarted(
            HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

HandlerInterceptorAdapter 抽象類:

package org.springframework.web.servlet.handler;

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

import org.springframework.web.servlet.AsyncHandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
 * Abstract adapter class for the HandlerInterceptor interface,
 * for simplified implementation of pre-only/post-only interceptors.
 *
 * @author Juergen Hoeller
 * @since 05.12.2003
 */
public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {

    /**
     * This implementation always returns {@code true}.
     */
    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 {
    }

    /**
     * This implementation is empty.
     */
    public void afterConcurrentHandlingStarted(
            HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

如上面的程式碼所示,其實在HandlerInterceptorAsyncHandlerInterceptor中還有很多的程式碼註釋,只是博主感覺太多了,就將其全部刪除啦!如果大家對這些註釋感興趣的話,可以自行檢視原始碼。下面,咱們以繼承HandlerInterceptorAdapter抽象類為例進行演示:

package com.hit.interceptor;

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

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

/**
 * @author 維C果糖
 * @create 2017-03-31
 */

public class WrongCodeInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("WrongCodeInterceptor, preHandle......");
        return true;
    }

    @Override
    public void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception {
        System.out.println("WrongCodeInterceptor, postHandle......");
    }

    @Override
    public void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("WrongCodeInterceptor, afterCompletion......");
    }

    @Override
    public void afterConcurrentHandlingStarted(
            HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("WrongCodeInterceptor, afterConcurrentHandlingStarted......");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

3.2 WebRequestInterceptor 介面

WebRequestInterceptor介面中也定義了 3 個方法,同HandlerInterceptor介面完全相同,咱們也是通過複寫這 3 個方法來使用者的請求進行攔截處理的。而且這 3 個方法都傳遞了同一個引數 WebRequest,那麼這個 WebRequest 到底是什麼呢?其實這個 WebRequest 是 Spring 中定義的一個介面,它裡面的方法定義跟 HttpServletRequest 類似,在WebRequestInterceptor中對 WebRequest 進行的所有操作都將同步到 HttpServletRequest 中,然後在當前請求中依次傳遞。

在 Spring 框架之中,還提供了一個和WebRequestInterceptor介面長的很像的抽象類,那就是:WebRequestInterceptorAdapter,其實現了AsyncHandlerInterceptor介面,並在內部呼叫了WebRequestInterceptor介面。

接下來,咱們主要講一下WebRequestInterceptor介面的 3 個函式:

  • preHandle(WebRequest request)方法,該方法在請求處理之前進行呼叫,也就是說,其會在 Controller 中的方法呼叫之前被呼叫。這個方法跟 HandlerInterceptor 中的 preHandle 不同,主要區別在於該方法的返回值是void 型別的,也就是沒有返回值,因此我們主要用它來進行資源的準備工作,比如我們在使用 Hibernate 的時候,可以在這個方法中準備一個 Hibernate 的Session 物件,然後利用 WebRequest 的 setAttribute(name, value, scope) 把它放到 WebRequest 的屬性中。在這裡,進一步說說 setAttribute 方法的第三個引數 scope ,該引數是一個Integer 型別的。在 WebRequest 的父層介面 RequestAttributes 中對它定義了三個常量,分別為:
    • SCOPE_REQUEST ,它的值是 0,表示只有在 request 中可以訪問。
    • SCOPE_SESSION,它的值是1,如果環境允許的話,它表示的是一個區域性的隔離的 session,否則就代表普通的 session,並且在該 session 範圍內可以訪問。
    • SCOPE_GLOBAL_SESSION,它的值是 2,如果環境允許的話,它表示的是一個全域性共享的 session,否則就代表普通的 session,並且在該 session 範圍內可以訪問。
  • postHandle(WebRequest request, ModelMap model)方法,該方法在請求處理之後,也就是在 Controller 中的方法呼叫之後被呼叫,但是會在檢視返回被渲染之前被呼叫,所以可以在這個方法裡面通過改變資料模型 ModelMap 來改變資料的展示。該方法有兩個引數,WebRequest 物件是用於傳遞整個請求資料的,比如在 preHandle 中準備的資料都可以通過 WebRequest 來傳遞和訪問;ModelMap 就是 Controller 處理之後返回的 Model 物件,咱們可以通過改變它的屬性來改變返回的 Model 模型。
  • afterCompletion(WebRequest request, Exception ex)方法,該方法會在整個請求處理完成,也就是在檢視返回並被渲染之後執行。因此可以在該方法中進行資源的釋放操作。而 WebRequest 引數就可以把咱們在 preHandle 中準備的資源傳遞到這裡進行釋放。Exception 引數表示的是當前請求的異常物件,如果在 Controller 中丟擲的異常已經被 Spring 的異常處理器給處理了的話,那麼這個異常物件就是是 null.

接下來,咱們在看看以上介面和抽象類的具體程式碼:

WebRequestInterceptor 介面:

package org.springframework.web.context.request;

import org.springframework.ui.ModelMap;

public interface WebRequestInterceptor {

    void preHandle(WebRequest request) throws Exception;

    void postHandle(WebRequest request, ModelMap model) throws Exception;

    void afterCompletion(WebRequest request, Exception ex) throws Exception;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

WebRequestInterceptorAdapter 抽象類:

package org.springframework.web.servlet.handler;

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

import org.springframework.util.Assert;
import org.springframework.web.context.request.AsyncWebRequestInterceptor;
import org.springframework.web.context.request.WebRequestInterceptor;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
 * Adapter that implements the Servlet HandlerInterceptor interface
 * and wraps an underlying WebRequestInterceptor.
 *
 * @author Juergen Hoeller
 * @since 2.0
 * @see org.springframework.web.context.request.WebRequestInterceptor
 * @see org.springframework.web.servlet.HandlerInterceptor
 */
public class WebRequestHandlerInterceptorAdapter implements AsyncHandlerInterceptor {

    private final WebRequestInterceptor requestInterceptor;


    /**
     * Create a new WebRequestHandlerInterceptorAdapter for the given WebRequestInterceptor.
     * @param requestInterceptor the WebRequestInterceptor to wrap
     */
    public WebRequestHandlerInterceptorAdapter(WebRequestInterceptor requestInterceptor) {
        Assert.notNull(requestInterceptor, "WebRequestInterceptor must not be null");
        this.requestInterceptor = requestInterceptor;
    }


    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        this.requestInterceptor.preHandle(new DispatcherServletWebRequest(request, response));
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception {

        this.requestInterceptor.postHandle(new DispatcherServletWebRequest(request, response),
                (modelAndView != null && !modelAndView.wasCleared() ? modelAndView.getModelMap() : null));
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {

        this.requestInterceptor.afterCompletion(new DispatcherServletWebRequest(request, response), ex);
    }

    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (this.requestInterceptor instanceof AsyncWebRequestInterceptor) {
            AsyncWebRequestInterceptor asyncInterceptor = (AsyncWebRequestInterceptor) this.requestInterceptor;
            DispatcherServletWebRequest webRequest = new DispatcherServletWebRequest(request, response);
            asyncInterceptor.afterConcurrentHandlingStarted(webRequest);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

如上面的程式碼所示,展示了WebRequestInterceptor介面和WebRequestInterceptorAdapter抽象類的原始碼。下面,咱們以實現WebRequestInterceptor介面為例進行演示:

package com.hit.interceptor;

import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.WebRequestInterceptor;

/**
 * @author 維C果糖
 * @create 2017-03-31
 */

public class WrongCodeInterceptor implements WebRequestInterceptor {

    @Override
    public void preHandle(WebRequest request) throws Exception {
        System.out.println("WrongCodeInterceptor, preHandle......");
    }

    @Override
    public void postHandle(WebRequest request, ModelMap model) throws Exception {
        System.out.println("WrongCodeInterceptor, postHandle......");
    }

    @Override
    public void afterCompletion(WebRequest request, Exception ex) throws Exception {
        System.out.println("WrongCodeInterceptor, afterCompletion......");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

3.3 AbstractInterceptor 抽象類

除了上面3.23.3所講的內容,咱們還可以通過繼承 Struts2 框架提供的AbstractInterceptor抽象類來實現攔截的功能。如果咱們在深入一點研究,會發現AbstractInterceptor實現了Interceptor介面,而Interceptor介面又繼承了Serializable介面。

Interceptor介面中,提供了 3 個方法供咱們使用,分別為init()destroy()intercept(),由於AbstractInterceptor實現了Interceptor介面,因此咱們就可以直接繼承AbstractInterceptor,然後複寫方法就可以啦!至於為什麼繼承AbstractInterceptor而不是直接實現Interceptor介面,是因為AbstractInterceptor已經幫咱們實現了空的init()destroy()方法,不需要咱們自己去複寫了,咱們直接複寫intercept()方法就可以啦!現在,咱們大致瞭解一下這 3 個方法的作用:

  • init()方法,一般用來進行初始化操作;
  • destroy()方法,一般用來進行釋放資源的操作;
  • intercept()方法,該方法是實現攔截功能的主要方法,咱們就在該方法中編寫攔截的邏輯。

接下來,咱們在看看以上介面和抽象類的具體程式碼:

Interceptor 介面:

package com.opensymphony.xwork2.interceptor;

import com.opensymphony.xwork2.ActionInvocation;

import java.io.Serializable;

public interface Interceptor extends Serializable {

    /**
     * Called to let an interceptor clean up any resources it has allocated.
     */
    void destroy();

    /**
     * Called after an interceptor is created, but before any requests are processed using
     * {@link #intercept(com.opensymphony.xwork2.ActionInvocation) intercept} , giving
     * the Interceptor a chance to initialize any needed resources.
     */
    void init();

    /**
     * Allows the Interceptor to do some processing on the request before and/or after the rest of the processing of the
     * request by the {@link ActionInvocation} or to short-circuit the processing and just return a String return code.
     *
     * @param invocation the action invocation
     * @return the return code, either returned from {@link ActionInvocation#invoke()}, or from the interceptor itself.
     * @throws Exception any system-level error, as defined in {@link com.opensymphony.xwork2.Action#execute()}.
     */
    String intercept(ActionInvocation invocation) throws Exception;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

AbstractInterceptor 介面:

package com.opensymphony.xwork2.interceptor;

import com.opensymphony.xwork2.ActionInvocation;

/**
 * Provides default implementations of optional lifecycle methods
 */
public abstract class AbstractInterceptor implements Interceptor {

    /**
     * Does nothing
     */
    public void init() {
    }

    /**
     * Does nothing
     */
    public void destroy() {
    }

    /**
     * Override to handle interception
     */
    public abstract String intercept(ActionInvocation invocation) throws Exception;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

如上面的程式碼所示,展示了Interceptor介面和AbstractInterceptor抽象類的原始碼。下面,咱們以繼承AbstractInterceptor抽象類為例進行演示:

package com.hit.interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import org.apache.struts2.ServletActionContext;


/**
 * @author 維C果糖
 * @create 2017-03-31
 */

public class WrongCodeInterceptor  extends AbstractInterceptor {

    /**
     * 通過攔截功能,驗證使用者是否登入
     */
    public String intercept(ActionInvocation invocation) throws Exception {

        UserInfo info = (UserInfo) ServletActionContext.getRequest().getSession().getAttribute("user");

        if(info != null && !info.getName().equals("") && !info.getPwd().equals(""))
        {
            return invocation.invoke();
        }
        return "login";
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

UserInfo 類檔案:

/**
 * @author 維C果糖
 * @create 2017-03-31
 */

public class UserInfo {
    String name;
    String pwd;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

4 配置攔截器

在前面,咱們用了很大篇幅的內容講述了攔截器如何實現,因此,我相信大家實現攔截器已經沒有問題啦!接下來,咱們在看看,如何在 XML 檔案中配置攔截器,使咱們的攔截器生效。

在配置攔截器之前,有 4 個名稱的概念需要大家先了解一下,分別為:Join PointPointcutAdviceAdvisor.

  • Join Point,表示“連線點”,它是程式執行中的某個階段點,比如方法的呼叫、異常的丟擲等;
  • Advice,表示“通知”,它是某個連線點所採用的處理邏輯,也就是向連線點注入的程式碼;
  • Pointcut,表示“切入點”,它是“連線點”的集合,是程式中需要注入 Advice 的位置的集合,指明 Advice 要在什麼樣的條件下才能被觸發;
  • Advisor,它是 Pointcut 和 Advice 的配置器,包括 Pointcut 和 Advice,是將 Advice 注入程式中 Pointcut 位置的程式碼。

接下來,給出 XML 配置檔案的宣告:

<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:mvc="http://www.springframework.org/schema/mvc"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
     http://www.springframework.org/schema/context  
     http://www.springframework.org/schema/context/spring-context-3.0.xsd  
     http://www.springframework.org/schema/mvc  
     http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在 XML 檔案的頭部宣告完之後,咱們就可以在 Spring 的配置檔案中就可以使用mvc標籤啦!而在mvc標籤中有一個名為mvc:interceptors的標籤,該標籤就是用於宣告 Spring 攔截器的。下面,給出一個配置示例:

<mvc:interceptors>  
    <!-- 使用 bean 定義一個 Interceptor,直接定義在 mvc:interceptors 下面的 Interceptor 將攔截所有的請求 -->  
    <bean class="com.hit.interceptor.WrongCodeInterceptor"/>  
    <mvc:interceptor>  
        <mvc:mapping path="/demo/hello.do"/>  
        <!-- 定義在 mvc:interceptor 下面的 Interceptor,表示對特定的請求進行攔截 -->  
        <bean class="com.hit.interceptor.LoginInterceptor"/>  
    </mvc:interceptor>  
</mvc:interceptors>  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在 Spring 的XML 配置檔案中,咱們可以通過mvc:interceptors標籤宣告一系列的攔截器,例如:

<mvc:interceptors>
        <bean class="com.hit.interceptor.ContextInterceptor"/>
        <bean class="com.hit.interceptor.LoginInterceptor"/>
        <bean class="com.hit.interceptor.WrongCodeInterceptor"/>
    </mvc:interceptors>
  • 1
  • 2
  • 3
  • 4
  • 5

如上所示,這些攔截器就夠成了一個攔截器鏈,或者稱之為攔截器棧。而這些攔截器的執行順序是按宣告的先後順序執行的,即:先宣告的攔截器先執行,後宣告的攔截器後執行。在mvc:interceptors標籤下宣告interceptor標籤主要有兩種方式:

  • 直接定義一個 Interceptor 實現類的 bean 物件,使用這種方式宣告的 Interceptor 攔截器將會對所有的請求進行攔截;
  • 使用mvc:interceptor標籤進行宣告,使用這種方式進行宣告的 Interceptor 可以通過mvc:mapping子標籤來定義需要進行攔截的請求路徑。

此外,由於攔截器是 AOP 程式設計思想的典型應用,也就意味著咱們可以“切”到具體的“面”進行某些操作。例如,

<bean id="WrongCodeInterceptor" class="com.hit.interceptor.WrongCodeInterceptor">
        <property name="userName" value="user-module"></property>
</bean>

<bean id="loginInterceptor" class="com.hit.interceptor.LoginInterceptor">
    <property name="excludePackages">
       <list>
          <value>com.hit.user.exception</value>
          <value>com.hit.order.exception</value>
       </list>
    </property>
</bean>

<aop:config>
    <aop:advisor advice-ref="WrongCodeInterceptor" pointcut="execution(* com.hit.*.demo..*.*(..)) || execution(* com.hit.*.demo..*.*(..)) " />
    <aop:advisor advice-ref="loginInterceptor" pointcut="execution(* com.hit.*.demo..*.*(..))" />
</aop:config>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

如上所示,咱們實現了切入到“面”進行特定的攔截功能,其中pointcut表示“切入點”,advisor表示要注入到pointcut的程式碼。大家可能會對pointcut中的*符合有所疑惑,它是“萬用字元”,表示可以匹配該位置上的任何名稱。當然,如果咱們要想使用aop標籤,就得先在配置檔案中就得進行宣告啦!此外,如果大家想進一步瞭解切入點pointcut的表示式的話,可以參考博文“ Spring 框架中切入點 pointcut 表示式的常用寫法 ”。

1 前言

  昨天新接了一個需要,“攔截 XXX,然後 OOO”,好吧,說白了就是要用攔截器乾點事(實現一個具體的功能)。之前,也在網路上搜了很多關於Interceptor的文章,但感覺內容都大同小異,而且知識點零零散散,不太方便閱讀。因此,正好藉此機會,整理一篇關於攔截器的文章,在此分享給大家,以供大家參考閱讀。

2 攔截器

2.1 概念

  Java 裡的攔截器是動態攔截 action 呼叫的物件。它提供了一種機制可以使開發者可以定義在一個 action 執行的前後執行的程式碼,也可以在一個 action 執行前阻止其執行,同時也提供了一種可以提取 action 中可重用部分的方式。在AOP(Aspect-Oriented Programming,面向切面程式設計)中攔截器用於在某個方法或欄位被訪問之前進行攔截,然後在之前或之後加入某些操作。

2.2 原理

  攔截器 Interceptor 的攔截功能是基於 Java 的動態代理來實現的,具體可以參考博文“

相關推薦

【轉】詳述 Spring MVC 框架攔截 Interceptor 的使用方法

1 前言   昨天新接了一個需要,“攔截 XXX,然後 OOO”,好吧,說白了就是要用攔截器乾點事(實現一個具體的功能)。之前,也在網路上搜了很多關於Interceptor的文章,但感覺內容都大同小異,而且知識點零零散散,不太方便閱讀。因此,正好藉此機會,整理一篇關於攔截器

詳述 Spring MVC 框架攔截 Interceptor 的使用方法

1 前言  昨天新接了一個需要,“攔截 XXX,然後 OOO”,好吧,說白了就是要用攔截器乾點事(實現一個具體的功能)。之前,也在網路上搜了很多關於Interceptor的文章,但感覺內容都大同小異,而且知識點零零散散,不太方便閱讀。因此,正好藉此機會,整理一篇關於攔截器的文

第四十章:Spring MVC框架攔截10

第八章 攔截器 攔截器最典型的用法是檢查使用者是否登入,登入後可以執行目標handler方法,未登入則跳轉到登入頁面。這樣的操作要是在每個攔截器內部來寫就太麻煩了,統一提取到攔截器中是明智之舉。 1.HandlerInterceptor介面 ①preHandle()方法 簽名:b

spring web.xml 攔截(Interceptor)的實現原理及程式碼示例

前言:前面2篇部落格,我們分析了Java中過濾器和監聽器的實現原理,今天我們來看看攔截器。1,攔截器的概念    java裡的攔截器是動態攔截Action呼叫的物件,它提供了一種機制可以使開發者在一個Action執行的前後執行一段程式碼,也可以在一個Action執行前阻止其執

Spring mvc登錄攔截

gin tor 要求 session row 請求轉發 pin dispatch framework 自己實現的第一個Spring mvc登錄攔截器 題目要求:拒絕未登錄用戶進入系統,只要發現用戶未登錄,則將用戶請求轉發到/login.do要求用戶登錄 實現步驟: 1.在s

spring mvc 能過攔截記錄請求數據和響應數據

style gpo exec point ret nature request 響應 處理 spring mvc 能過攔截器記錄請求數據記錄有很多種方式,主要有以下三種: 1:過濾器 2:HandlerInterceptor攔截器 3:Aspect接口控制器 但是就我個人所

spring boot之spring mvc常用配置--攔截配置(4)

2.攔截器配置 攔截器Interceptor實現對每一個請求處理前後進行相關的業務處理。類似於Servlet的Filter。 第一種方式:可以讓普通的bean實現HandlerInterceptor介面或者繼承HandlerInterceptorAdapter類來實現自定義

Spring MVC配置及攔截的實現

如題所示,這裡主要是介紹攔截器的使用了但是為了更貼合實際的專案所以我們先匯入spring mvc框架。為了使用spring mvc我們要匯入相關的包,它依賴於spring-web 和spring -webmvc我這裡的版本是4.0.6的。將相關的包匯入到工程中並且新增編譯

spring mvc定義登入攔截(不登入不讓訪問相關資源),為什麼要放權/login.do(就是不攔截/login.do)?

spring.xml攔截器配置如下: <mvc:interceptor> <mvc:mapping path="/**" /><mvc:exclude-mapping path="/login.do" /><bean class="

Spring AOP及MethodInterceptor攔截實現方法攔截以及切入點函式阻止執行

package com.rhxy.utils; import com.rhxy.bean_new.personnel.Employee; import com.rhxy.bean_new.personnel.User; import com.rhxy.dao_new.EmployeeDAO; import c

Spring MVC 整合攔截Interceptor

目錄 Interceptor 簡介 Interceptor 實現方法 HandlerInterceptor 介面 HandlerInterceptor 介面 AsyncHandlerInterceptor 介面 HandlerInterceptorAdapter 

通過攔截Interceptor實現Spring MVCController介面訪問資訊的記錄

java web工程專案使用了Spring+Spring MVC+Hibernate的結構,在Controller中的方法都是用於處理前端的訪問資訊,Controller通過呼叫Service進行業務處理後給前端返回ModelAndView物件或者只返回Json格式資料。如

Spring mvc攔截Interceptor

1 功能 Java 裡的攔截器是動態攔截 action 呼叫的物件。它提供了一種機制可以使開發者可以定義在一個 action 執行的前後執行的程式碼,也可以在一個 action 執行前阻止其執行,同時也提供了一種可以提取 action 中可重用部分的方式。在AOP(Aspe

spring mvc攔截配置mvc:interceptors

ria letter lec 成了 -a font 進行 匹配 eight 其實在mvc:interceptors標簽中,有兩種類型的配置,一種直接配置一個bean(bean和ref歸為一類),另一種還要配置上攔截的路徑和排除的路徑。直接配置的bean那就代表對所有的請求進

Spring MVC 攔截”處理模型資料 (二) @ModelAttribute

在這裡強烈建議看看我之前寫的幾篇關於SpringMVC的部落格,都是串通的。 @ModelAttribute這個是SpringMVC中處理模型資料的最難也是最重要的點。相當於以前Struct的攔截器。

談談spring攔截interceptor

談談spring中的攔截器        在web開發中,攔截器是經常用到的功能。它可以幫我們驗證是否登陸、預先設定資料以及統計方法的執行效率等等。今天就來詳細的談一下spring中的攔截器。spring中攔截器主要分兩種,一個是HandlerInterceptor,一個

27.Spring-Boot攔截靜態資源的處理(踩過坑)以及Spring mvc configuring拓展介紹

一.springboot中對靜態資源的處理  預設情況下,springboot提供存放放置靜態資源的資料夾:  /static  /public   /resources  /META-INF/resources 對於maven專案即就是存在src/main/re

spring security 單一賬戶多地方登陸提醒, ajax 攔截 Interceptor

lean odi true window post 錯誤 img commons 會話管理 spring-security.xml部分代碼: <http auto-config="false" > <access-denied-h

spring框架定時的配置及應用

首先我們來簡單瞭解下定時器:  1. 定時器的作用             在實際的開發中,如果專案中需要定時執行或者需要重複執行一定的工作,定時器

Spring Boot (Web 篇):整合攔截Interceptor

目錄 說在前面 在pom.xml加入相關依賴 定義攔截器 編寫攔截器 Interceptor 註冊攔截器 Interceptor 頁面訪問(專案啟動) 總結 原始碼下載 說在前面 Struts2(Interceptor篇):攔截器的實現