欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

關(guān)于Spring MVC框架中攔截器Interceptor的使用解讀

 更新時(shí)間:2023年07月10日 09:08:22   作者:CG國斌  
這篇文章主要介紹了關(guān)于Spring MVC框架中攔截器Interceptor的使用,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

1 前言

網(wǎng)絡(luò)上關(guān)于Interceptor的文章,但感覺內(nèi)容都大同小異,而且知識點(diǎn)零零散散,不太方便閱讀。

因此,整理一篇關(guān)于攔截器的文章,在此分享給大家,以供大家參考閱讀。

2 攔截器

2.1 概念

Java 里的攔截器是動態(tài)攔截action調(diào)用的對象。它提供了一種機(jī)制可以使開發(fā)者可以定義在一個action執(zhí)行的前后執(zhí)行的代碼,也可以在一個action執(zhí)行前阻止其執(zhí)行,同時(shí)也提供了一種可以提取action中可重用部分的方式。

在 AOP(Aspect-Oriented Programming,面向切面編程)中攔截器用于在某個方法(包括構(gòu)造器)或字段被訪問之前進(jìn)行攔截,然后在之前或之后加入某些操作。

特別地,現(xiàn)階段 Spring 自身僅支持基于方法的攔截操作!如果基于方法的攔截操作不能滿足需求,可以使用 AspectJ 與 Spring 進(jìn)行集成,以實(shí)現(xiàn)更細(xì)粒度或更多方面的攔截操作。

2.2 原理

攔截器Interceptor的攔截功能是基于 Java 的動態(tài)代理來實(shí)現(xiàn)的,具體可以參考博文「用 Java 實(shí)現(xiàn)攔截器 Interceptor 的攔截功能 」,也可以通過閱讀 Spring 源代碼來了解更為權(quán)威的實(shí)現(xiàn)細(xì)節(jié)。

3 實(shí)現(xiàn)方法

在 Spring 框架之中,我們要想實(shí)現(xiàn)攔截器的功能,主要通過兩種途徑,第一種是實(shí)現(xiàn)HandlerInterceptor接口,第二種是實(shí)現(xiàn)WebRequestInterceptor接口。接下來,我們分別詳細(xì)的介紹兩者的實(shí)現(xiàn)方法。

3.1 HandlerInterceptor 接口

HandlerInterceptor接口中,定義了 3 個方法,分別為preHandle()、postHandle()afterCompletion(),我們就是通過復(fù)寫這 3 個方法來對用戶的請求進(jìn)行攔截處理的。

因此,我們可以通過直接實(shí)現(xiàn)HandlerInterceptor接口來實(shí)現(xiàn)攔截器的功能。不過在 Spring 框架之中,其還提供了另外一個接口和一個抽象類,實(shí)現(xiàn)了對HandlerInterceptor接口的功能擴(kuò)展,分別為:AsyncHandlerInterceptorHandlerInterceptorAdapter.

對于AsyncHandlerInterceptor接口,其在繼承HandlerInterceptor接口的同時(shí),又聲明了一個新的方法afterConcurrentHandlingStarted();而HandlerInterceptorAdapter抽象類,則是更進(jìn)一步,在其繼承AsyncHandlerInterceptor接口的同時(shí),又復(fù)寫了preHandle方法。因此,AsyncHandlerInterceptor更像是一個過渡的接口。

在實(shí)際應(yīng)用中,我們一般都是通過實(shí)現(xiàn)HandlerInterceptor接口或者繼承HandlerInterceptorAdapter抽象類,復(fù)寫preHandle()、postHandle()afterCompletion()這 3 個方法來對用戶的請求進(jìn)行攔截處理的。

下面,我們就詳細(xì)介紹這個 3 個方法。

  • preHandle(HttpServletRequest request, HttpServletResponse response, Object handle)方法

該方法在請求處理之前進(jìn)行調(diào)用。

Spring MVC 中的Interceptor是鏈?zhǔn)秸{(diào)用的,在一個應(yīng)用中或者說是在一個請求中可以同時(shí)存在多個Interceptor

每個Interceptor的調(diào)用會依據(jù)它的聲明順序依次執(zhí)行,而且最先執(zhí)行的都是Interceptor中的preHandle方法,所以可以在這個方法中進(jìn)行一些前置初始化操作或者是對當(dāng)前請求做一個預(yù)處理,也可以在這個方法中進(jìn)行一些判斷來決定請求是否要繼續(xù)進(jìn)行下去。

該方法的返回值是布爾(Boolean)類型的,當(dāng)它返回為false時(shí),表示請求結(jié)束,后續(xù)的Interceptor和控制器(Controller)都不會再執(zhí)行;當(dāng)返回值為true時(shí),就會繼續(xù)調(diào)用下一個InterceptorpreHandle方法,如果已經(jīng)是最后一個Interceptor的時(shí)候,就會是調(diào)用當(dāng)前請求的控制器中的方法。

  • postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView)方法

通過preHandle方法的解釋,我們知道這個方法包括后面要說到的afterCompletion方法都只能在當(dāng)前所屬的InterceptorpreHandle方法的返回值為true的時(shí)候,才能被調(diào)用。

postHandle方法在當(dāng)前請求進(jìn)行處理之后,也就是在控制器中的方法調(diào)用之后執(zhí)行,但是它會在DispatcherServlet進(jìn)行視圖返回渲染之前被調(diào)用,所以我們可以在這個方法中對控制器處理之后的ModelAndView對象進(jìn)行操作。

postHandle方法被調(diào)用的方向跟preHandle是相反的,也就是說,先聲明的InterceptorpostHandle方法反而會后執(zhí)行。

這和 Struts2 里面的Interceptor的執(zhí)行過程有點(diǎn)類似,Struts2 里面的Interceptor的執(zhí)行過程也是鏈?zhǔn)降模皇窃?Struts2 里面需要手動調(diào)用ActionInvocationinvoke方法來觸發(fā)對下一個Interceptor或者是action的調(diào)用,然后每一個Interceptor中在invoke方法調(diào)用之前的內(nèi)容都是按照聲明順序執(zhí)行的,而invoke方法之后的內(nèi)容就是反向的。

  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex)方法

也是需要當(dāng)前對應(yīng)的InterceptorpreHandle方法的返回值為true時(shí)才會執(zhí)行。

因此,該方法將在整個請求結(jié)束之后,也就是在DispatcherServlet渲染了對應(yīng)的視圖之后執(zhí)行,這個方法的主要作用是用于進(jìn)行資源清理的工作。

接下來,我們在看看以上接口和抽象類的具體代碼:

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;
}

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;
}

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 {
	}
}

如上面的代碼所示,其實(shí)在HandlerInterceptorAsyncHandlerInterceptor中還有很多的代碼注釋,只是博主感覺太多了,就將其全部刪除了。

如果大家對這些注釋感興趣的話,可以自行查看源代碼。

下面,我們以繼承HandlerInterceptorAdapter抽象類為例進(jìn)行演示:

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......");
    }
}

3.2 WebRequestInterceptor 接口

WebRequestInterceptor接口中也定義了 3 個方法,同HandlerInterceptor接口完全相同,我們也是通過復(fù)寫這 3 個方法來對用戶的請求進(jìn)行攔截處理的。

而且這 3 個方法都傳遞了同一個參數(shù)WebRequest,那么這個WebRequest到底是什么呢?

其實(shí)這個WebRequest是 Spring 中定義的一個接口,它里面的方法定義跟HttpServletRequest類似,在WebRequestInterceptor中對WebRequest進(jìn)行的所有操作都將同步到HttpServletRequest中,然后在當(dāng)前請求中依次傳遞。

在 Spring 框架之中,還提供了一個和WebRequestInterceptor接口長的很像的抽象類,那就是:WebRequestInterceptorAdapter,其實(shí)現(xiàn)了AsyncHandlerInterceptor接口,并在內(nèi)部調(diào)用了WebRequestInterceptor接口。

接下來,我們主要講一下WebRequestInterceptor接口的 3 個函數(shù):

  • preHandle(WebRequest request)方法

該方法在請求處理之前進(jìn)行調(diào)用,也就是說,其會在控制器中的方法調(diào)用之前被調(diào)用。

這個方法跟HandlerInterceptor中的preHandle不同,主要區(qū)別在于該方法的返回值是void類型的,也就是沒有返回值,因此我們主要用它來進(jìn)行資源的準(zhǔn)備工作,比如我們在使用 Hibernate 的時(shí)候,可以在這個方法中準(zhǔn)備一個 Hibernate 的Session對象,然后利用WebRequestsetAttribute(name, value, scope)把它放到WebRequest的屬性中。

在這里,進(jìn)一步說說setAttribute方法的第三個參數(shù)scope,該參數(shù)是一個Integer類型的。

WebRequest的父層接口RequestAttributes中對它定義了三個常量,

分別為:

SCOPE_REQUEST,它的值是0,表示只有在request中可以訪問。

SCOPE_SESSION,它的值是1,如果環(huán)境允許的話,它表示的是一個局部的隔離的session,否則就代表普通的session,并且在該session范圍內(nèi)可以訪問。

SCOPE_GLOBAL_SESSION,它的值是2,如果環(huán)境允許的話,它表示的是一個全局共享的session,否則就代表普通的session,并且在該session范圍內(nèi)可以訪問。

  • postHandle(WebRequest request, ModelMap model)方法

該方法在請求處理之后,也就是在控制器中的方法調(diào)用之后被調(diào)用,但是會在視圖返回被渲染之前被調(diào)用,所以可以在這個方法里面通過改變數(shù)據(jù)模型ModelMap來改變數(shù)據(jù)的展示。該方法有兩個參數(shù),WebRequest對象是用于傳遞整個請求數(shù)據(jù)的,比如在preHandle中準(zhǔn)備的數(shù)據(jù)都可以通過WebRequest來傳遞和訪問;ModelMap就是控制器處理之后返回的Model對象,我們可以通過改變它的屬性來改變返回的Model模型。

  • afterCompletion(WebRequest request, Exception ex)方法

該方法會在整個請求處理完成,也就是在視圖返回并被渲染之后執(zhí)行。因此可以在該方法中進(jìn)行資源的釋放操作。而WebRequest參數(shù)就可以把我們在preHandle中準(zhǔn)備的資源傳遞到這里進(jìn)行釋放。

Exception參數(shù)表示的是當(dāng)前請求的異常對象,如果在控制器中拋出的異常已經(jīng)被 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;
}

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);
		}
	}
}

如上面的代碼所示,展示了WebRequestInterceptor接口和WebRequestInterceptorAdapter抽象類的源碼。

下面,我們以實(shí)現(xiàn)WebRequestInterceptor接口為例進(jìn)行演示:

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......");
    }
}

3.3 AbstractInterceptor 抽象類

除了上面3.23.3所講的內(nèi)容,我們還可以通過繼承 Struts2 框架提供的AbstractInterceptor抽象類來實(shí)現(xiàn)攔截的功能。如果我們在深入一點(diǎn)研究,會發(fā)現(xiàn)AbstractInterceptor實(shí)現(xiàn)了Interceptor接口,而Interceptor接口又繼承了Serializable接口。

Interceptor接口中,提供了 3 個方法供我們使用,分別為init()destroy()intercept(),由于AbstractInterceptor實(shí)現(xiàn)了Interceptor接口,因此我們就可以直接繼承AbstractInterceptor,然后復(fù)寫方法就可以啦!

至于為什么繼承AbstractInterceptor而不是直接實(shí)現(xiàn)Interceptor接口,是因?yàn)?code>AbstractInterceptor已經(jīng)幫我們實(shí)現(xiàn)了空的init()destroy()方法,不需要我們自己去復(fù)寫了,我們直接復(fù)寫intercept()方法就可以了。

現(xiàn)在,我們大致了解一下這 3 個方法的作用:

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

接下來,我們再看看以上接口和抽象類的具體代碼:

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;
}

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;
}

如上面的代碼所示,展示了Interceptor接口和AbstractInterceptor抽象類的源碼。

下面,我們以繼承AbstractInterceptor抽象類為例進(jìn)行演示:

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 {
	/**
     * 通過攔截功能,驗(yàn)證用戶是否登錄
     */
    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";
    }
}

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;
    }
}

4 配置攔截器

在前面,我們用了很大篇幅的內(nèi)容講述了攔截器如何實(shí)現(xiàn),因此,我相信大家對于如何實(shí)現(xiàn)攔截器已經(jīng)沒有問題啦!

接下來,我們在看看,如何在 XML 文件中配置攔截器,以使我們的攔截器生效。

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

  • Join Point,表示“連接點(diǎn)”,它是程序運(yùn)行中的某個階段點(diǎn),比如方法的調(diào)用、異常的拋出等;
  • Advice,表示“通知”,它是某個連接點(diǎn)所采用的處理邏輯,也就是向連接點(diǎn)注入的代碼;
  • Pointcut,表示“切入點(diǎn)”,它是“連接點(diǎn)”的集合,是程序中需要注入Advice的位置的集合,指明Advice要在什么樣的條件下才能被觸發(fā);
  • 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">  

在 XML 文件的頭部聲明完成之后,我們就可以在 Spring 的配置文件中使用mvc標(biāo)簽啦!

而在mvc標(biāo)簽中有一個名為mvc:interceptors的標(biāo)簽,該標(biāo)簽就是用于聲明 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,表示對特定的請求進(jìn)行攔截 -->  
        <bean class="com.hit.interceptor.LoginInterceptor"/>  
    </mvc:interceptor>  
</mvc:interceptors>  

在 Spring 的XML 配置文件中,我們可以通過mvc:interceptors標(biāo)簽聲明一系列的攔截器,例如:

<mvc:interceptors>
    <bean class="com.hit.interceptor.ContextInterceptor"/>
    <bean class="com.hit.interceptor.LoginInterceptor"/>
    <bean class="com.hit.interceptor.WrongCodeInterceptor"/>
</mvc:interceptors>

如上所示,這些攔截器就構(gòu)成了一個攔截器鏈,或者稱之為攔截器棧。這些攔截器的執(zhí)行順序是按聲明的先后順序執(zhí)行的,即:先聲明的攔截器先執(zhí)行,后聲明的攔截器后執(zhí)行。

mvc:interceptors標(biāo)簽下聲明interceptor標(biāo)簽主要有兩種方式:

  • 直接定義一個Interceptor實(shí)現(xiàn)類的bean對象,使用這種方式聲明的Interceptor攔截器將會對所有的請求進(jìn)行攔截;
  • 使用mvc:interceptor標(biāo)簽進(jìn)行聲明,使用這種方式進(jìn)行聲明的Interceptor可以通過mvc:mapping子標(biāo)簽來定義需要進(jìn)行攔截的請求路徑。

此外,由于攔截器是 AOP 編程思想的典型應(yīng)用,也就意味著我們可以“切”到具體的“面”進(jìn)行某些操作。例如,

<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..*.*(..)) " />
	<aop:advisor advice-ref="loginInterceptor" pointcut="execution(* com.hit.*.demo..*.*(..))" />
</aop:config>

如上所示,我們實(shí)現(xiàn)了切入到“面”進(jìn)行特定的攔截功能,其中pointcut表示“切入點(diǎn)”,advisor表示要注入到pointcut的代碼。

實(shí)際上,如果在多個攔截器配置中,pointcut表達(dá)式都相同,我們可以將其抽取出來,單獨(dú)聲明,然后通過pointcut-ref標(biāo)簽進(jìn)行引用,這樣可以稍微簡化一些配置!

除此之外,大家可能會對pointcut中的*符號有所疑惑,它是“通配符”,表示可以匹配該位置上的任何名稱。

當(dāng)然,如果我們要想使用aop標(biāo)簽,就得先在配置文件中進(jìn)行聲明啦!

最后,如果大家想進(jìn)一步了解切入點(diǎn)pointcut表達(dá)式的話,可以參考「Spring 框架中切入點(diǎn) pointcut 表達(dá)式的常用寫法 」。

總結(jié)

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot使用Redis實(shí)現(xiàn)分布式鎖

    SpringBoot使用Redis實(shí)現(xiàn)分布式鎖

    這篇文章主要為大家詳細(xì)介紹了SpringBoot使用Redis實(shí)現(xiàn)分布式鎖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • tio-boot整合hotswap-classloader實(shí)現(xiàn)熱加載方法實(shí)例

    tio-boot整合hotswap-classloader實(shí)現(xiàn)熱加載方法實(shí)例

    這篇文章主要為大家介紹了tio-boot整合hotswap-classloader實(shí)現(xiàn)熱加載方法實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Mybatis超詳細(xì)講解構(gòu)建SQL方法

    Mybatis超詳細(xì)講解構(gòu)建SQL方法

    這篇文章主要為大家詳細(xì)介紹了Mybatis構(gòu)建SQL,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-07-07
  • 關(guān)于通過Java連接mysql對反斜杠”\“轉(zhuǎn)義的測試詳解

    關(guān)于通過Java連接mysql對反斜杠”\“轉(zhuǎn)義的測試詳解

    這篇文章主要給大家介紹了關(guān)于通過Java連接mysql對反斜杠”\“轉(zhuǎn)義的測試的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家理解反斜杠”\“轉(zhuǎn)義具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。
    2017-06-06
  • Springboot項(xiàng)目消費(fèi)Kafka數(shù)據(jù)的方法

    Springboot項(xiàng)目消費(fèi)Kafka數(shù)據(jù)的方法

    本文詳細(xì)介紹了如何在Spring Boot項(xiàng)目中配置和實(shí)現(xiàn)Kafka消費(fèi)者和生產(chǎn)者,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2025-01-01
  • Java數(shù)據(jù)結(jié)構(gòu)與算法之二分查找詳解

    Java數(shù)據(jù)結(jié)構(gòu)與算法之二分查找詳解

    這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)與算法之二分查找詳解,二分查找算法是一種在有序數(shù)組中查找某一特定元素的搜索算法,其思想就是不斷地將有序查找表“一分為二”,逐漸縮小搜索區(qū)域,進(jìn)而找到目標(biāo)元素,需要的朋友可以參考下
    2023-12-12
  • SpringBoot實(shí)現(xiàn)模塊日志入庫的項(xiàng)目實(shí)踐

    SpringBoot實(shí)現(xiàn)模塊日志入庫的項(xiàng)目實(shí)踐

    本文主要介紹了SpringBoot實(shí)現(xiàn)模塊日志入庫的項(xiàng)目實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Java基礎(chǔ)教程之?dāng)?shù)組的定義與使用

    Java基礎(chǔ)教程之?dāng)?shù)組的定義與使用

    Java語言的數(shù)組是一個由固定長度的特定類型元素組成的集合,它們的數(shù)據(jù)類型必須相同,聲明變量的時(shí)候,必須要指定參數(shù)類型,這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)教程之?dāng)?shù)組的定義與使用的相關(guān)資料,需要的朋友可以參考下
    2021-09-09
  • SWT(JFace)體驗(yàn)之圓環(huán)狀(戒指型)

    SWT(JFace)體驗(yàn)之圓環(huán)狀(戒指型)

    SWT(JFace)體驗(yàn)之圓環(huán)狀(戒指型)實(shí)現(xiàn)代碼。
    2009-06-06
  • Java數(shù)據(jù)結(jié)構(gòu)之有效隊(duì)列定義與用法示例

    Java數(shù)據(jù)結(jié)構(gòu)之有效隊(duì)列定義與用法示例

    這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)之有效隊(duì)列定義與用法,結(jié)合實(shí)例形式分析了java有效隊(duì)列的數(shù)據(jù)插入、刪除、判斷、計(jì)算等相關(guān)操作技巧,需要的朋友可以參考下
    2017-10-10

最新評論