SpringMVC的處理器攔截器HandlerInterceptor詳解
簡介
SpringWebMVC的處理器攔截器,類似于Servlet開發(fā)中的過濾器Filter,用于處理器進(jìn)行預(yù)處理和后處理。
應(yīng)用場景
1、日志記錄,可以記錄請求信息的日志,以便進(jìn)行信息監(jiān)控、信息統(tǒng)計(jì)等。
2、權(quán)限檢查:如登陸檢測,進(jìn)入處理器檢測是否登陸,如果沒有直接返回到登陸頁面。
3、性能監(jiān)控:典型的是慢日志。
HandlerInterceptor
public interface HandlerInterceptor {
/**
* 預(yù)處理回調(diào)方法,實(shí)現(xiàn)處理器的預(yù)處理(如檢查登陸),第三個參數(shù)為響應(yīng)的處理器,自定義Controller
* 返回值:true表示繼續(xù)流程(如調(diào)用下一個攔截器或處理器);false表示流程中斷(如登錄檢查失?。粫^續(xù)調(diào)用其他的攔截器或處理器,此時我們需要通過response來產(chǎn)生響應(yīng);
*/
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception;
/**
* 后處理回調(diào)方法,實(shí)現(xiàn)處理器的后處理(但在渲染視圖之前),此時我們可以通過modelAndView(模型和視圖對象)對模型數(shù)據(jù)進(jìn)行處理或?qū)σ晥D進(jìn)行處理,modelAndView也可能為null。
*/
void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception;
/**
* 整個請求處理完畢回調(diào)方法,即在視圖渲染完畢時回調(diào),如性能監(jiān)控中我們可以在此記錄結(jié)束時間并輸出消耗時間,還可以進(jìn)行一些資源清理,類似于try-catch-finally中的finally,但僅調(diào)用處理器執(zhí)行鏈中
*/
void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception;
}攔截器適配器HandlerInterceptorAdapter
有時候我們可能只需要實(shí)現(xiàn)三個回調(diào)方法中的某一個,如果實(shí)現(xiàn)HandlerInterceptor接口的話,三個方法必須實(shí)現(xiàn),不管你需不需要,此時spring提供了一個HandlerInterceptorAdapter適配器(種適配器設(shè)計(jì)模式的實(shí)現(xiàn)),允許我們只實(shí)現(xiàn)需要的回調(diào)方法。
public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {
/**
* 默認(rèn)是true
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
/**
* This implementation is empty.
*/
@Override
public void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
}
/**
* This implementation is empty.
*/
@Override
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
/**
* 不是HandlerInterceptor的接口實(shí)現(xiàn),是AsyncHandlerInterceptor的,AsyncHandlerInterceptor實(shí)現(xiàn)了HandlerInterceptor
*/
@Override
public void afterConcurrentHandlingStarted(
HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
}
}這樣在我們業(yè)務(wù)中比如要記錄系統(tǒng)日志,日志肯定是在afterCompletion之后記錄的,否則中途失敗了,也記錄了,那就扯淡了。一定是程序正常跑完后,我們記錄下那些對數(shù)據(jù)庫做個增刪改的操作日志進(jìn)數(shù)據(jù)庫。所以我們只需要繼承HandlerInterceptorAdapter,并重寫afterCompletion一個方法即可,因?yàn)閜reHandle默認(rèn)是true。

運(yùn)行流程總結(jié)如下:
1、攔截器執(zhí)行順序是按照Spring配置文件中定義的順序而定的。
2、會先按照順序執(zhí)行所有攔截器的preHandle方法,一直遇到return false為止,比如第二個preHandle方法是return false,則第三個以及以后所有攔截器都不會執(zhí)行。若都是return true,則按順序加載完preHandle方法。
3、然后執(zhí)行主方法(自己的controller接口),若中間拋出異常,則跟return false效果一致,不會繼續(xù)執(zhí)行postHandle,只會倒序執(zhí)行afterCompletion方法。
4、在主方法執(zhí)行完業(yè)務(wù)邏輯(頁面還未渲染數(shù)據(jù))時,按倒序執(zhí)行postHandle方法。若第三個攔截器的preHandle方法return false,則會執(zhí)行第二個和第一個的postHandle方法和afterCompletion(postHandle都執(zhí)行完才會執(zhí)行這個,也就是頁面渲染完數(shù)據(jù)后,執(zhí)行after進(jìn)行清理工作)方法。(postHandle和afterCompletion都是倒序執(zhí)行)
正常流程Demo
package com.bshf.recipe.demo.syslog;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SyslogInterceptor implements HandlerInterceptor {
/**
* 預(yù)處理回調(diào)方法,實(shí)現(xiàn)處理器的預(yù)處理(如檢查登陸),第三個參數(shù)為響應(yīng)的處理器,自定義Controller
* 返回值:true表示繼續(xù)流程(如調(diào)用下一個攔截器或處理器);false表示流程中斷(如登錄檢查失?。粫^續(xù)調(diào)用其他的攔截器或處理器,此時我們需要通過response來產(chǎn)生響應(yīng);
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("==========================================1================================================");
return true;
}
/**
* 后處理回調(diào)方法,實(shí)現(xiàn)處理器的后處理(但在渲染視圖之前),此時我們可以通過modelAndView(模型和視圖對象)對模型數(shù)據(jù)進(jìn)行處理或?qū)σ晥D進(jìn)行處理,modelAndView也可能為null。
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("==========================================post1================================================");
}
/**
* 整個請求處理完畢回調(diào)方法,即在視圖渲染完畢時回調(diào),如性能監(jiān)控中我們可以在此記錄結(jié)束時間并輸出消耗時間,還可以進(jìn)行一些資源清理,類似于try-catch-finally中的finally,但僅調(diào)用處理器執(zhí)行鏈中
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("==========================================after1================================================");
}
}package com.bshf.recipe.demo.syslog;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SyslogInterceptor2 implements HandlerInterceptor {
/**
* 預(yù)處理回調(diào)方法,實(shí)現(xiàn)處理器的預(yù)處理(如檢查登陸),第三個參數(shù)為響應(yīng)的處理器,自定義Controller
* 返回值:true表示繼續(xù)流程(如調(diào)用下一個攔截器或處理器);false表示流程中斷(如登錄檢查失?。?,不會繼續(xù)調(diào)用其他的攔截器或處理器,此時我們需要通過response來產(chǎn)生響應(yīng);
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("==========================================2================================================");
return true;
}
/**
* 后處理回調(diào)方法,實(shí)現(xiàn)處理器的后處理(但在渲染視圖之前),此時我們可以通過modelAndView(模型和視圖對象)對模型數(shù)據(jù)進(jìn)行處理或?qū)σ晥D進(jìn)行處理,modelAndView也可能為null。
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("==========================================post2================================================");
}
/**
* 整個請求處理完畢回調(diào)方法,即在視圖渲染完畢時回調(diào),如性能監(jiān)控中我們可以在此記錄結(jié)束時間并輸出消耗時間,還可以進(jìn)行一些資源清理,類似于try-catch-finally中的finally,但僅調(diào)用處理器執(zhí)行鏈中
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("==========================================after2================================================");
}
}package com.bshf.recipe.demo.syslog;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SyslogInterceptor3 implements HandlerInterceptor {
/**
* 預(yù)處理回調(diào)方法,實(shí)現(xiàn)處理器的預(yù)處理(如檢查登陸),第三個參數(shù)為響應(yīng)的處理器,自定義Controller
* 返回值:true表示繼續(xù)流程(如調(diào)用下一個攔截器或處理器);false表示流程中斷(如登錄檢查失?。?,不會繼續(xù)調(diào)用其他的攔截器或處理器,此時我們需要通過response來產(chǎn)生響應(yīng);
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("==========================================3================================================");
return true;
}
/**
* 后處理回調(diào)方法,實(shí)現(xiàn)處理器的后處理(但在渲染視圖之前),此時我們可以通過modelAndView(模型和視圖對象)對模型數(shù)據(jù)進(jìn)行處理或?qū)σ晥D進(jìn)行處理,modelAndView也可能為null。
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("==========================================post3================================================");
}
/**
* 整個請求處理完畢回調(diào)方法,即在視圖渲染完畢時回調(diào),如性能監(jiān)控中我們可以在此記錄結(jié)束時間并輸出消耗時間,還可以進(jìn)行一些資源清理,類似于try-catch-finally中的finally,但僅調(diào)用處理器執(zhí)行鏈中
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("==========================================after3================================================");
}
}<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.bshf.recipe.demo.syslog.SyslogInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.bshf.recipe.demo.syslog.SyslogInterceptor2" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.bshf.recipe.demo.syslog.SyslogInterceptor3" />
</mvc:interceptor>
</mvc:interceptors><mvc:mapping path="/**"/>需要攔截的路徑,這里匹配所有。這里的配置順序?qū)⑹菙r截器執(zhí)行順序。
輸出結(jié)果
==========================================1================================================
==========================================2================================================
==========================================3================================================
==========================================post3================================================
==========================================post2================================================
==========================================post1================================================
==========================================after3================================================
==========================================after2================================================
==========================================after1================================================
post和after是倒序的?。。?!
中斷流程Demo
將SyslogInterceptor3的preHandle方法返回false。其他不變,再看輸出結(jié)果
==========================================1================================================
==========================================2================================================
==========================================3================================================
==========================================after2================================================
==========================================after1================================================
發(fā)現(xiàn)沒有了post,post方法一個都沒有輸出。不僅如此,你的主程序代碼(xxx.controller的一個接口)都不會被執(zhí)行,所以只要遇到return false,則直接進(jìn)行after清理工作,post和自己主程序代碼都將被略過。
到此這篇關(guān)于SpringMVC的處理器攔截器HandlerInterceptor詳解的文章就介紹到這了,更多相關(guān)攔截器HandlerInterceptor內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 深入解析Spring MVC中攔截器Interceptor的實(shí)現(xiàn)原理和應(yīng)用場景
- Spring?Boot?Interceptor的原理、配置、順序控制及與Filter的關(guān)鍵區(qū)別對比分析
- SpringBoot使用Mybatis-Plus中分頁插件PaginationInterceptor詳解
- Spring Boot攔截器Interceptor與過濾器Filter深度解析(區(qū)別、實(shí)現(xiàn)與實(shí)戰(zhàn)指南)
- Spring Mvc中攔截器Interceptor用法解讀
- Spring Boot攔截器Interceptor與過濾器Filter詳細(xì)教程(示例詳解)
- Spring攔截器之HandlerInterceptor使用方式
- Spring的攔截器HandlerInterceptor詳解
- spring中Interceptor的使用小結(jié)
相關(guān)文章
Springboot實(shí)現(xiàn)公共字段填充的示例詳解
這篇文章主要為大家詳細(xì)介紹了Springboot實(shí)現(xiàn)公共字段填充的相關(guān)知識,文中的示例代碼講解詳細(xì),對我們深入學(xué)習(xí)springboot有一定的幫助,感興趣的小伙伴可以了解下2023-10-10
Java 異步編程實(shí)踐_動力節(jié)點(diǎn)Java學(xué)院整理
異步編程提供了一個非阻塞的,事件驅(qū)動的編程模型。下面通過本文給大家介紹Java 異步編程實(shí)踐,感興趣的的朋友一起看看吧2017-05-05
hutool實(shí)戰(zhàn):IoUtil 流操作工具類(將內(nèi)容寫到流中)
這篇文章主要介紹了Go語言的io.ioutil標(biāo)準(zhǔn)庫使用,是Golang入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下,如果能給你帶來幫助,請多多關(guān)注腳本之家的其他內(nèi)容2021-06-06
Java設(shè)置session超時的幾種方式總結(jié)
這篇文章主要介紹了Java設(shè)置session超時的幾種方式總結(jié)的相關(guān)資料,需要的朋友可以參考下2017-07-07
MybatisPlus使用Mybatis的XML的動態(tài)SQL的功能實(shí)現(xiàn)多表查詢
本文主要介紹了MybatisPlus使用Mybatis的XML的動態(tài)SQL的功能實(shí)現(xiàn)多表查詢,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-11-11
詳解Spring中@Valid和@Validated注解用法
本文將以新增一個員工為功能切入點(diǎn),以常規(guī)寫法為背景,慢慢烘托出?@Valid?和?@Validated?注解用法詳解,文中的示例代碼講解詳細(xì),感興趣的可以了解一下2022-07-07
springboot接入cachecloud redis示例實(shí)踐
這篇文章主要介紹了springboot接入cachecloud redis示例實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10

