歡迎關(guān)注公眾號(hào):邏魔代碼
我們知道晕讲,在Java Web開發(fā)時(shí),若想對(duì)請(qǐng)求或響應(yīng)做出統(tǒng)一的邏輯處理马澈,可以使用過濾器或者攔截器瓢省。那么具體什么時(shí)候使用過濾器,什么時(shí)候使用攔截器呢痊班?
在探究這個(gè)問題之前勤婚,我們先搞清楚,什么是 Servlet 涤伐?
Servlet
現(xiàn)在我們通常做 Java Web 開發(fā)都會(huì)用 SpringBoot 馒胆,但要知道 SpringBoot 只是用來簡化開發(fā)的荆永,在此之前,Springframework 只是一個(gè)粘合劑框架国章,用來整合各種 Java Web 技術(shù)的具钥,SpringMvc 都是出現(xiàn)的比較晚的技術(shù),更早之前是 Struts2液兽、Struts1骂删。
那更早之前呢?就是基于原始的 Servlet/JSP 四啰。
javax.servlet 和 jaavx.servlet.http 包提供了一些接口和類宁玫,實(shí)現(xiàn)了 Servlet 規(guī)范。 javax.servlet 包中的 Servlet 聲明了一些重要方法柑晒,如 init(), service(), desctroy() 等欧瘪,這些也都是 servlet 的生命周期方法.
我們還知道,Servlet 是運(yùn)行于 Servlet 容器中的匙赞。容器可以處理網(wǎng)絡(luò)連接佛掖,解析 HTTP 請(qǐng)求等。Tomcat 就是最負(fù)盛名的一個(gè)容器涌庭。
雖然現(xiàn)在大家都用 Spring 全家桶做開發(fā)芥被,但必須要知道 SpringWvc 的核心還是一個(gè) DispatcherServlet,其本質(zhì)也就是一個(gè) Servlet.
過濾器 Filter
過濾器是被容器執(zhí)行的類坐榆。請(qǐng)求在進(jìn)入容器時(shí)拴魄、響應(yīng)在離開容器時(shí),會(huì)經(jīng)過一個(gè)個(gè)的過濾器席镀。過濾器的實(shí)例匹中,在容器中是以過濾器鏈的形式執(zhí)行的。
如果在應(yīng)用中豪诲,我們定義了多個(gè)過濾器顶捷,那么執(zhí)行的先后順序,可以通過 @Order
注解來指定跛溉。
Filter 接口的核心方法焊切,也是其生命周期方法:
-
init(FilterConfig config)
- 此方法只調(diào)用一次,用于初始化過濾器 -
doFilter(HttpServletRequest request, HttpServletResponse response, FilterChian chian)
- 此方法在每一個(gè)請(qǐng)求打到映射的資源上時(shí)都會(huì)調(diào)用芳室,比如定義一個(gè) Filter 攔截 /path/* 专肪,那么每一個(gè)匹配 /path/* 訪問資源的請(qǐng)求進(jìn)來時(shí),都會(huì)執(zhí)行此方法堪侯。這個(gè)方法中就是攔截器的具體邏輯 -
destroy()
- 此方法也只執(zhí)行一次嚎尤,用于銷毀過濾器
攔截器 Interceptor
Spring 攔截器類似于 Servlet 過濾器。攔截器允許自定義預(yù)處理(Pre-Processing)伍宦,在其中可以選擇禁止對(duì)應(yīng) Handler 的執(zhí)行芽死;也允許自定義后處理(Post-Precessing)乏梁;在攔截器中可以訪問 Spring Context 上下文。
HandlerInterceptor 的核心方法:
-
preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
- 該方法在請(qǐng)求到達(dá) Controller 之前執(zhí)行操作关贵,返回一個(gè)布爾值遇骑。當(dāng)返回 false 時(shí),不再執(zhí)行對(duì)應(yīng)的 handler -
postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
- 該方法在響應(yīng)返回客戶端之前執(zhí)行 -
afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception)
- 該方法在請(qǐng)求和響應(yīng)流程完成之后執(zhí)行
HandlerInterceptor
: 它的實(shí)例在 DispatcherServlet
(javax.servlet.Servlet 的實(shí)例) 中作為請(qǐng)求處理的一部分來執(zhí)行揖曾。
注意落萎,現(xiàn)在實(shí)現(xiàn) Spring 攔截器,只需要實(shí)現(xiàn) HandlerInterceptor
接口即可炭剪,更早之前练链,接口的方法不能有默認(rèn)實(shí)現(xiàn)時(shí),是需要繼承 HandlerInteceptorAdapter
這個(gè)抽象類的奴拦,現(xiàn)在這個(gè)類已經(jīng)可以廢棄了媒鼓。
通過下面一張圖看看過濾器和攔截器的位置:
Filters vs HandlerInterceptors
- Filter 是 Servlet 規(guī)范中的,而 HandlerInterceptor 是 Spring 中的一個(gè)概念
- 攔截器位置相對(duì)于過濾器更靠后
- 精細(xì)的預(yù)處理任務(wù)適用于攔截器错妖,如授權(quán)檢查等
- 內(nèi)容處理相關(guān)或通用的流程绿鸣,非常適合用過濾器;如上傳表單站玄、zip 壓縮枚驻、圖像處理濒旦、日志記錄請(qǐng)求株旷、身份驗(yàn)證等
-
HandlerInterceptor 的
postHandle
方法允許我們向視圖添加更多模型對(duì)象,但不能更改 HttpServletResponse尔邓,因?yàn)樗呀?jīng)被提交了 - 過濾器的
doFilter
方法比攔截器的postHandle
更通用晾剖。我們可以在過濾器中改變請(qǐng)求或響應(yīng),并將其傳遞給鏈梯嗽,甚至阻止請(qǐng)求的處理 - HandlerInterceptor 提供了比過濾器更精細(xì)的控制齿尽,因?yàn)槲覀兛梢栽L問實(shí)際的目標(biāo) handler,甚至可以檢查 handler 方法是否有某個(gè)特定的注解
歡迎關(guān)注公眾號(hào):邏魔代碼