關(guān)于Spring MVC框架中攔截器Interceptor的使用解讀
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ò)展,分別為:AsyncHandlerInterceptor
和HandlerInterceptorAdapter
.
對于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)用下一個Interceptor
的preHandle
方法,如果已經(jīng)是最后一個Interceptor
的時(shí)候,就會是調(diào)用當(dāng)前請求的控制器中的方法。
postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView)
方法
通過preHandle
方法的解釋,我們知道這個方法包括后面要說到的afterCompletion
方法都只能在當(dāng)前所屬的Interceptor
的preHandle
方法的返回值為true
的時(shí)候,才能被調(diào)用。
postHandle
方法在當(dāng)前請求進(jìn)行處理之后,也就是在控制器中的方法調(diào)用之后執(zhí)行,但是它會在DispatcherServlet
進(jìn)行視圖返回渲染之前被調(diào)用,所以我們可以在這個方法中對控制器處理之后的ModelAndView
對象進(jìn)行操作。
postHandle
方法被調(diào)用的方向跟preHandle
是相反的,也就是說,先聲明的Interceptor
的postHandle
方法反而會后執(zhí)行。
這和 Struts2 里面的Interceptor
的執(zhí)行過程有點(diǎn)類似,Struts2 里面的Interceptor
的執(zhí)行過程也是鏈?zhǔn)降模皇窃?Struts2 里面需要手動調(diào)用ActionInvocation
的invoke
方法來觸發(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)的Interceptor
的preHandle
方法的返回值為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í)在HandlerInterceptor
和AsyncHandlerInterceptor
中還有很多的代碼注釋,只是博主感覺太多了,就將其全部刪除了。
如果大家對這些注釋感興趣的話,可以自行查看源代碼。
下面,我們以繼承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
對象,然后利用WebRequest
的setAttribute(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.2
和3.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
、Advice
和Advisor
:
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)分布式鎖
這篇文章主要為大家詳細(xì)介紹了SpringBoot使用Redis實(shí)現(xiàn)分布式鎖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05tio-boot整合hotswap-classloader實(shí)現(xiàn)熱加載方法實(shí)例
這篇文章主要為大家介紹了tio-boot整合hotswap-classloader實(shí)現(xiàn)熱加載方法實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12關(guān)于通過Java連接mysql對反斜杠”\“轉(zhuǎn)義的測試詳解
這篇文章主要給大家介紹了關(guān)于通過Java連接mysql對反斜杠”\“轉(zhuǎn)義的測試的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家理解反斜杠”\“轉(zhuǎn)義具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。2017-06-06Springboot項(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-01Java數(shù)據(jù)結(jié)構(gòu)與算法之二分查找詳解
這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)與算法之二分查找詳解,二分查找算法是一種在有序數(shù)組中查找某一特定元素的搜索算法,其思想就是不斷地將有序查找表“一分為二”,逐漸縮小搜索區(qū)域,進(jìn)而找到目標(biāo)元素,需要的朋友可以參考下2023-12-12SpringBoot實(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-04Java基礎(chǔ)教程之?dāng)?shù)組的定義與使用
Java語言的數(shù)組是一個由固定長度的特定類型元素組成的集合,它們的數(shù)據(jù)類型必須相同,聲明變量的時(shí)候,必須要指定參數(shù)類型,這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)教程之?dāng)?shù)組的定義與使用的相關(guān)資料,需要的朋友可以參考下2021-09-09SWT(JFace)體驗(yàn)之圓環(huán)狀(戒指型)
SWT(JFace)體驗(yàn)之圓環(huán)狀(戒指型)實(shí)現(xiàn)代碼。2009-06-06Java數(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