SpringMVC一步到位精通攔截器
前言
在上一篇文章中講完了SpringMVC的大部分知識,此篇文章中主要講解攔截器。上一篇文章??
攔截器的使用是非常普遍的。例如在 OA系統(tǒng)中通過攔截器可以攔截未登錄的用戶,或者使用它來驗證己登錄用戶是否有相應(yīng)的操作權(quán)限等。SpringMVC
中提供了攔截器功能,通過配置即可對請求進行攔截處理。
攔截器概述
SpringMVC 中的攔截器 (Interceptor
)類似于 Servlet 中的過濾器(Filter
),它主要用于攔截用戶請求并做相應(yīng)的處理。例如通過攔截器可以進行權(quán)限驗證、判斷用戶是否己登錄等。
攔截器的定義
要使用SpringMVC中的攔截器,就需要對攔截器類進行定義和配置。通常攔截器類可以通過兩種方式來定義:
- 一種是通過實現(xiàn)
HandlerInterceptor
接口或者繼承HandlerInterceptor
接口的實現(xiàn)類(如HandlerInterceptorAdapter
)來定義。 - 另一種是通過實現(xiàn)
WebRequestInterceptor
接口或繼承WebRequestInterceptor
接口的實現(xiàn)類來定義。
實現(xiàn)HandlerInterceptor
接口的定義方式為例,自定義攔截器類的代碼如下所示:
public class UserInterceptor implements HandlerInterceptor { public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler) throws Exception { System.out.println("UserInterceptor...preHandle"); //對攔截的請求進行放行處理(true為放行,false為不放行) return true; } public void postHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("UserInterceptor...postHandle"); } public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("UserInterceptor...afterCompletion"); } }
從上述代碼可以看出,自定義的攔截器類實現(xiàn)了 HandlerInterceptor
接口,并實現(xiàn)了接口中的3 個方法。關(guān)于這3個方法的具體描述如下:
preHandle()
方法:該方法會在控制器方法前執(zhí)行,其返回值表示是否中斷后續(xù)操作。當(dāng)其返回值為true
時,表示繼續(xù)向下執(zhí)行; 當(dāng)其返回值為false
時,會中斷后續(xù)的所有操作(包括調(diào)用下一個攔截器和控制器類中的方法執(zhí)行等)。postHandle()
方法:該方法會在控制器方法調(diào)用之后,且解析視圖之前執(zhí)行。可以通過此方法對請求域中的模型和視圖做出進一步的修改。afterCompletion()
方法:該方法在整個請求完成,即視圖渲染結(jié)束之后執(zhí)行??梢酝ㄟ^此方法實現(xiàn)一些資源清理、記錄日志信息等工作。
攔截器的配置
要使自定義的攔截器類生效,需要在SpringMVC的配置文件中進行配置,配置代碼如下:
<!--配置攔截器--> <mvc:interceptors> <!--使用bean直接定義在<mvc:interceptor>下面的Interceptor 將攔截所有請求--> <bean class="com.hzy.interceptor.UserInterceptor"/> <!--攔截器1--> <mvc:interceptor> <!--配置攔截器作用的路徑--> <mvc:mapping path="/**"/> <!--配置不需要攔截器作用的路徑--> <mvc:exclude-mapping path=""/> <!--定義在<mvc:interceptor>下面,表示對匹配路徑的請求才進行攔截--> <bean class="com.hzy.interceptor.Interceptor1"/> </mvc:interceptor> <!--攔截器2--> <mvc:interceptor> <mvc:mapping path="/hello"/> <bean class="com.hzy.interceptor.Interceptor2"/> </mvc:interceptor> ...... </mvc:interceptors>
在上述代碼中, <mvc:interceptors>
元素用于配置一組攔截器,其子元素<bean>
中定義的是全局攔截器,它會攔截所有的請求;而<mvc:interceptor>
元素中定義的是指定路徑的攔截器,它會對指定路徑下的請求生效。<mvc:interceptor>
元素的子元素<mvc:mapping>
用于配置攔截器作用的路徑,該路徑在其屬性 path
中定義。如上述代碼中 path
的屬性值 “/**”
表示攔截所有路徑, “/hello”
表示攔截所有以“hello”
結(jié)尾的路徑。如果在請求路徑中包含不需要攔截的內(nèi)容,還可以通過 <mvc:exclude-mapping>
元素進行配置。
攔截器的執(zhí)行流程
攔截器的執(zhí)行是有一定順序的,該順序與配置文件中所定義的攔截器的順序相關(guān)。
單個攔截器的執(zhí)行流程
如果在項目中只定義了一個攔截器,那么該攔截器在程序中的執(zhí)行流程如下圖所示。從中可以看出,程序首先會執(zhí)行攔截器類中的 preHandle()
方法,如果該方法的返回值為 true
,則程序就會繼續(xù)向下執(zhí)行處理器中的方法,否則將不再向下執(zhí)行:在業(yè)務(wù)處理器(即控制器Controller
類)處理完請求后,會執(zhí)行 postHandle()
方法,然后通過 DispatcherServlet
向客戶端返回響應(yīng);在 DispatcherServlet
處理完請求后,才會執(zhí)行 afterCompletion()
方法。
簡單的案例
web.xml中配置SpringMVC的前端過濾器和初始化加載配置文件等信息。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <servlet> <!--配置前端過濾器--> <servlet-name>spring-mvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--初始化時加載配置文件--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-config.xml</param-value> </init-param> <!--表示容器在啟動時立即加載Servlet--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring-mvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
在src下創(chuàng)建com.hzy.controller包,并在里面創(chuàng)建控制器類HelloController
,
@Controller public class HelloController { @RequestMapping("/hello") public String hello(){ System.out.println("Hello"); return "success"; } }
在src下創(chuàng)建com.hzy.interceptor包,并在里面創(chuàng)建攔截器類UserInterceptor
,該類需要實現(xiàn)HandlerInterceptor
接口。
public class UserInterceptor implements HandlerInterceptor { public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler) throws Exception { System.out.println("UserInterceptor...preHandle"); //對攔截的請求進行放行處理(true為放行,false為不放行) return true; } public void postHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("UserInterceptor...postHandle"); } public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("UserInterceptor...afterCompletion"); } }
在resources目錄下創(chuàng)建springmvc-config.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--指定需要掃描的包--> <context:component-scan base-package="com.hzy.controller"/> <!--定義視圖解析器--> <bean id="internalResourceViewResolve" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!--設(shè)置前綴--> <property name="prefix" value="/WEB-INF/jsp/"/> <!--設(shè)置后綴--> <property name="suffix" value=".jsp"/> </bean> <mvc:annotation-driven/> <!--配置攔截器--> <mvc:interceptors> <!--使用bean直接定義在<mvc:interceptor>下面的Interceptor 將攔截所有請求--> <bean class="com.hzy.interceptor.UserInterceptor"/> </mvc:interceptors> </beans>
在WEB-INF目錄下創(chuàng)建一個jsp文件夾,并在里面創(chuàng)建一個頁面文件success.jsp,然后在<body>
里面顯示任意信息。發(fā)布并啟動項目,訪問http://localhost:8080/springMvc_SSM/hello (注意你的訪問路徑可能和我不一樣哦)
結(jié)果:
控制臺
多個攔截器的執(zhí)行流程
在大型項目中,通常會定義很多攔截器來實現(xiàn)不同的功能。多個攔截器的執(zhí)行順序如圖所示。這里假設(shè)有兩個攔截器 Interceptor1
和 Interceptor2
,并且在配置文件中,Interceptor1
攔截器配置在前。
從圖上可以看出,當(dāng)有多個攔截器同時工作時,它們的preHandle()
方法會按照配置文件中攔截器的配置順序執(zhí)行,而它們的postHandle()
方法和afterCompletion()
方法則會按照配置順序的反序執(zhí)行。
下為了驗證上述描述,下面就修改上面的代碼來演示多個攔截器的執(zhí)行。
在com.hzy.interceptor包中創(chuàng)建兩個攔截器類Interceptor1和Interceptor2。
Interceptor1.java
public class Interceptor1 implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("Interceptor1...preHandle"); return true; } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("Interceptor1...postHandle"); } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("Interceptor1...afterCompletion"); } }
Interceptor2.java
public class Interceptor2 implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("Interceptor2...preHandle"); return true; } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("Interceptor2...postHandle"); } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("Interceptor2...afterCompletion"); } }
springmvc-config.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--指定需要掃描的包--> <context:component-scan base-package="com.hzy.controller"/> <!--定義視圖解析器--> <bean id="internalResourceViewResolve" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!--設(shè)置前綴--> <property name="prefix" value="/WEB-INF/jsp/"/> <!--設(shè)置后綴--> <property name="suffix" value=".jsp"/> </bean> <mvc:annotation-driven/> <!--配置攔截器--> <mvc:interceptors> <!--使用bean直接定義在<mvc:interceptor>下面的Interceptor 將攔截所有請求--> <bean class="com.hzy.interceptor.UserInterceptor"/> <!--攔截器1--> <mvc:interceptor> <!--配置攔截器作用的路徑--> <mvc:mapping path="/**"/> <!--配置不需要攔截器作用的路徑--> <!-- <mvc:exclude-mapping path=""/>--> <!--定義在<mvc:interceptor>下面,表示對匹配路徑的請求才進行攔截--> <bean class="com.hzy.interceptor.Interceptor1"/> </mvc:interceptor> <!--攔截器2--> <mvc:interceptor> <mvc:mapping path="/hello"/> <bean class="com.hzy.interceptor.Interceptor2"/> </mvc:interceptor> </mvc:interceptors> </beans>
上述攔截器的配置代碼中,第一個攔截器會作用于所有路徑下的請求,而第二個攔截器會作用于“/hello”
結(jié)尾的請求。運行項目得到結(jié)果:
頁面輸出跟前面一樣。
控制臺輸出:
從圖中可以看出,程序先執(zhí)行了前面兩個攔截器類中的preHandle()
方法,這兩個方法的執(zhí)行順序與配置文件中定義的順序相同;然后執(zhí)行了控制器中類中的hello()
方法;最后執(zhí)行了兩個攔截器類中的postHandle()
方法和afterCompletion()
方法,且這兩個方法的執(zhí)行順序與配置文件中所定義的攔截器順序相反。
到此這篇關(guān)于SpringMVC一步到位精通攔截器的文章就介紹到這了,更多相關(guān)SpringMVC攔截器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis-plus實現(xiàn)主鍵自增和自動注入時間的示例代碼
這篇文章主要介紹了Mybatis-plus實現(xiàn)主鍵自增和自動注入時間的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07基于Jenkins搭建.NET Core持續(xù)集成環(huán)境過程圖解
這篇文章主要介紹了基于Jenkins搭建.NET Core持續(xù)集成環(huán)境過程圖解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-08-08Java數(shù)據(jù)結(jié)構(gòu)之圖的兩種搜索算法詳解
在很多情況下,我們需要遍歷圖,得到圖的一些性質(zhì)。有關(guān)圖的搜索,最經(jīng)典的算法有深度優(yōu)先搜索和廣度優(yōu)先搜索,接下來我們分別講解這兩種搜索算法,需要的可以參考一下2022-11-11ConcurrentHashMap線程安全及實現(xiàn)原理實例解析
這篇文章主要介紹了ConcurrentHashMap線程安全及實現(xiàn)原理實例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-11-11IntelliJ?IDEA設(shè)置JVM運行參數(shù)的圖文介紹
這篇文章主要介紹了IntelliJ?IDEA設(shè)置JVM運行參數(shù)的方法,包括配置方式及優(yōu)先級,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-04-04Spring框架中Bean的三種配置和實例化方法總結(jié)
在Spring框架中,Bean的配置和實例化是很重要的基礎(chǔ)內(nèi)容,掌握各種配置方式,才能靈活管理Bean對象,本文將全面介紹Bean的別名配置、作用范圍配置,以及構(gòu)造器實例化、工廠實例化等方式2023-10-10解析Spring框架中的XmlBeanDefinitionStoreException異常情況
這篇文章主要介紹了解析Spring框架中的XmlBeanDefinitionStoreException異常情況,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04