詳解Spring 攔截器流程及多個(gè)攔截器的執(zhí)行順序
攔截器是 Spring MVC 中的組件,它可以在進(jìn)入請(qǐng)求方法前做一些操作,也可以在請(qǐng)求方法后和渲染視圖后做一些事情。
攔截器的定義
SpringMVC 的攔截器只需要實(shí)現(xiàn) HandlerInterceptor 接口,并進(jìn)行配置即可。HandlerInterceptor 接口的定義如下:
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
在 HandlerInterceptor 中共有三個(gè)方法,每個(gè)方法的含義如下:
preHandler:進(jìn)入請(qǐng)求方法之前執(zhí)行;
postHandler:請(qǐng)求方法執(zhí)行完成之后執(zhí)行;
afterCompletion:視圖渲染后執(zhí)行。
攔截器的執(zhí)行流程
在 preHandle 方法中,它的返回值是 boolean 類型的,它的返回值影響著請(qǐng)求方法,以及 postHandle 和 afterCompletion 的執(zhí)行。具體如下。

也就是說(shuō),在 preHandle 中如果返回 false,那么后續(xù)的流程將不被執(zhí)行,這可能也是攔截器命名的由來(lái)。
測(cè)試攔截器
寫(xiě)一個(gè)簡(jiǎn)單攔截器,代碼如下:
@Slf4j
public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("preHandler");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("postHandler");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("afterCompletion");
}
}
創(chuàng)建了一個(gè) TestInterceptor 的監(jiān)聽(tīng)器類,它實(shí)現(xiàn)了 HandlerInterceptor 的所有接口。寫(xiě)完 TestInterceptor 還需要進(jìn)行注冊(cè)。代碼如下:
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(testInterceptor());
}
再來(lái)寫(xiě)一個(gè)簡(jiǎn)單的請(qǐng)求方法,代碼如下:
@GetMapping("test")
public String test()
{
return "test";
}
來(lái)啟動(dòng)我們的項(xiàng)目,并進(jìn)行訪問(wèn),控制臺(tái)的輸出如下:
2021-05-05 16:02:08.110 INFO 88509 --- [nio-8081-exec-6] com.example.demo.TestInterceptor : preHandler 2021-05-05 16:02:08.111 INFO 88509 --- [nio-8081-exec-6] com.example.demo.TestInterceptor : postHandler 2021-05-05 16:02:08.111 INFO 88509 --- [nio-8081-exec-6] com.example.demo.TestInterceptor : afterCompletion
多個(gè)攔截器的執(zhí)行順序
我們來(lái)寫(xiě)多個(gè)相同的監(jiān)聽(tīng)器,分別是 TestInterceptor、TestInterceptor2 和 TestInterceptor3。然后我們進(jìn)行注冊(cè),注冊(cè)代碼如下:
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(testInterceptor());
registry.addInterceptor(testInterceptor2());
registry.addInterceptor(testInterceptor3());
}
請(qǐng)求我們的方法,輸出如下:
2021-05-05 16:09:57.735 INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor : preHandler 2021-05-05 16:09:57.736 INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor2 : preHandler2 2021-05-05 16:09:57.736 INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor3 : preHandler3 2021-05-05 16:09:57.755 INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor3 : postHandler3 2021-05-05 16:09:57.755 INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor2 : postHandler2 2021-05-05 16:09:57.755 INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor : postHandler 2021-05-05 16:09:57.755 INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor3 : afterCompletion3 2021-05-05 16:09:57.755 INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor2 : afterCompletion2 2021-05-05 16:09:57.755 INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor : afterCompletion
注意觀察輸出的順序,preHandle 方法是按注冊(cè)順序進(jìn)行執(zhí)行的,而 postHandle 和 afterCompletion 跟注冊(cè)順序是相反的。
讓 preHandle 進(jìn)行攔截
我們讓 TestInterceptor2 的 preHandle 返回值為 false,然后查看一下輸出內(nèi)容。
2021-05-05 16:14:00.997 INFO 88582 --- [nio-8081-exec-1] com.example.demo.TestInterceptor : preHandler 2021-05-05 16:14:00.998 INFO 88582 --- [nio-8081-exec-1] com.example.demo.TestInterceptor2 : preHandler2 2021-05-05 16:14:00.998 INFO 88582 --- [nio-8081-exec-1] com.example.demo.TestInterceptor : afterCompletion
可以看到,TestInterceptor2 的 preHandle 的返回值為 false 以后,相當(dāng)于在 TestInterceptor2 的 preHandle 后續(xù)流程則不再繼續(xù)執(zhí)行了。
我們調(diào)整一下注冊(cè)的順序,代碼如下:
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(testInterceptor2());
registry.addInterceptor(testInterceptor());
registry.addInterceptor(testInterceptor3());
}
修改順序后的輸出如下:
2021-05-05 16:17:23.956 INFO 88589 --- [nio-8081-exec-1] com.example.demo.TestInterceptor2 : preHandler2
可以看到它后面的流程都被攔截了,沒(méi)有機(jī)會(huì)執(zhí)行了。
總結(jié)
攔截器是使用一個(gè) List 進(jìn)行保存,我們可以在項(xiàng)目中添加多個(gè)攔截器來(lái)完成不同的功能,比如可以進(jìn)行 Token 的驗(yàn)證,權(quán)限的獲取等。我們可以放到不同的攔截器中來(lái)進(jìn)行相關(guān)的操作。
以上就是詳解Spring 攔截器流程及多個(gè)攔截器的執(zhí)行順序的詳細(xì)內(nèi)容,更多關(guān)于Spring 攔截器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaMail實(shí)現(xiàn)簡(jiǎn)單郵件發(fā)送
這篇文章主要為大家詳細(xì)介紹了JavaMail實(shí)現(xiàn)簡(jiǎn)單郵件發(fā)送,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08
MyBatis動(dòng)態(tài)sql查詢及多參數(shù)查詢方式
這篇文章主要介紹了MyBatis動(dòng)態(tài)sql查詢及多參數(shù)查詢方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10
教你如何在IDEA?中添加?Maven?項(xiàng)目的?Archetype(解決添加不起作用的問(wèn)題)
這篇文章主要介紹了如何在?IDEA?中添加?Maven?項(xiàng)目的?Archetype(解決添加不起作用的問(wèn)題),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
Java報(bào)錯(cuò)net.dean.jraw.http.NetworkException異常的原因及解決方法
在開(kāi)發(fā)涉及網(wǎng)絡(luò)通信的Java應(yīng)用程序時(shí),我們經(jīng)常需要處理各種網(wǎng)絡(luò)異常,net.dean.jraw.http.NetworkException是在使用jRAW庫(kù)時(shí)可能遇到的一個(gè)異常,本文將詳細(xì)探討NetworkException的成因,并提供多種解決方案,需要的朋友可以參考下2024-12-12
在SpringBoot中配置MySQL數(shù)據(jù)庫(kù)的詳細(xì)指南
在 Spring Boot 中配置數(shù)據(jù)庫(kù)是一個(gè)相對(duì)簡(jiǎn)單的過(guò)程,通常涉及到以下幾個(gè)步驟:添加數(shù)據(jù)庫(kù)驅(qū)動(dòng)依賴、配置數(shù)據(jù)源屬性、以及可選的配置 JPA(如果使用),下面是小編給大家編寫(xiě)的一個(gè)詳細(xì)的指南,以MySQL 數(shù)據(jù)庫(kù)為例,需要的朋友可以參考下2024-12-12
Java設(shè)計(jì)模式中的單一責(zé)任原則詳解
這篇文章主要介紹了Java設(shè)計(jì)模式中的單一責(zé)任原則詳解,應(yīng)該有且僅有一個(gè)原因引起類的變更,即單一指責(zé)原則要求一個(gè)借口或類只有一個(gè)原因引起變化,也就是一個(gè)接口或類只有一個(gè)職責(zé),它就負(fù)責(zé)一件事情,需要的朋友可以參考下2023-11-11
Spring整合Kaptcha谷歌驗(yàn)證碼工具的開(kāi)發(fā)步驟
這篇文章主要介紹了Spring整合Kaptcha谷歌驗(yàn)證碼工具的開(kāi)發(fā)步驟,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01
Java?synchornized與ReentrantLock處理并發(fā)出現(xiàn)的錯(cuò)誤
synchronized機(jī)制提供了對(duì)每個(gè)對(duì)象相關(guān)的隱式監(jiān)視器鎖,并強(qiáng)制所有鎖的獲取和釋放都必須在同一個(gè)塊結(jié)構(gòu)中。當(dāng)獲取了多個(gè)鎖時(shí),必須以相反的順序釋放。即synchronized對(duì)于鎖的釋放是隱式的2023-01-01
springboot項(xiàng)目啟動(dòng),但是訪問(wèn)報(bào)404錯(cuò)誤的問(wèn)題
這篇文章主要介紹了springboot項(xiàng)目啟動(dòng),但是訪問(wèn)報(bào)404錯(cuò)誤的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12

