攔截器,過濾器,監聽器各有什麼作用?
大家好,我是IT修真院武漢分院第15期的學員,一枚正直純潔善良的java程式設計師
今天給大家分享一下,修真院官網Java任務五,深度思考中的知識點——攔截器,過濾器,監聽器
1.背景介紹
攔截器
Interceptor是動態攔截Action呼叫的物件。它提供了一種機制可以使開發者可以定義在一個Action執行的前後執行的程式碼,也可以在一個Action執行前阻止其執行 。同時也提供了一種可以提取Action中可重用的部分的方式。
過濾器
Filter是實現了javax.servlet.Filter介面的伺服器端程式,主要的用途是過濾字元編碼,做一些業務邏輯判斷,過濾器隨web應用啟動而啟動,只初始化一次,只有當web應用停止或重新部署才銷燬
監聽器
Listener是實現了javax.servlet.ServletContextListener介面的伺服器端程式,它也是隨web應用的啟動而啟動,只初始化了一次,隨web應用的停止而銷燬.
2.知識剖析
攔截器的實現方法: 主要通過兩種途徑,第一種是實現HandlerInterceptor介面,第二種是實現WebRequestInterceptor介面。
(1)HandlerInterceptor 介面
在該介面中,定義了 3 個方法,分別為preHandle()、postHandle()和afterCompletion(),通過複寫這 3 個方法來對使用者的請求進行攔截處理。
而且在 Spring 框架中,還提供了另外一個介面和一個抽象類,實現了對HandlerInterceptor介面的功能擴充套件,分別為:AsyncHandlerInterceptor和HandlerInterceptorAdapter.
在實際應用中,一般都是通過實現HandlerInterceptor介面或者繼承HandlerInterceptorAdapter抽象類
1)preHandle方法,該方法在請求處理之前進行呼叫。
SpringMVC 中的 Interceptor 是鏈式呼叫的,在一個請求中可以同時存在多個 Interceptor 。每個 Interceptor 的呼叫會依據它的宣告順序依次執行,而且最先執行的都是preHandle 方法,因此可以在這個方法中進行一些前置初始化操作或者是對當前請求做一個預處理,也可以進行一些判斷來決定請求是否要繼續進行下去。
當它返回為 false 時,表示請求結束,後續的 Interceptor 和 Controller 都不會再執行;
當返回值為 true 時,就會繼續呼叫下一個 Interceptor 的 preHandle 方法,如果已經是最後一個 Interceptor 的時候,就會呼叫當前請求的 Controller 中的方法。
2)postHandle方法在在當前所屬的 Interceptor 的 preHandle 方法的返回值為 true 的時候,才能被呼叫。
當前請求被處理之後,也就是在 Controller 中的方法呼叫之後執行,但是它會在 DispatcherServlet 進行檢視返回渲染之前被呼叫,所以可以在這個方法中對 Controller 處理之後的 ModelAndView 物件進行操作。
postHandle 方法被呼叫的方向跟 preHandle 是相反的,先宣告的 postHandle 方法反而會後執行。
3)afterCompletion方法,也是需要當前對應的 Interceptor 的 preHandle 方法的返回值為 true 時才會執行。因此,該方法將在整個請求結束之後,也就是在 DispatcherServlet 渲染了對應的檢視之後執行,這個方法的主要作用是用於進行資源清理的工作。
(2)WebRequestInterceptor 介面
在此介面中也定義了 3 個方法,同HandlerInterceptor介面完全相同,也需要複寫這 3 個方法來對使用者的請求進行攔截處理。而且這 3 個方法都傳遞了同一個引數 WebRequest。
它裡面的方法定義跟 HttpServletRequest 類似,在WebRequestInterceptor中對 WebRequest 進行的所有操作都將同步到 HttpServletRequest 中,然後在當前請求中依次傳遞。
1)preHandle(WebRequest request)方法,該方法跟 HandlerInterceptor 中的 preHandle 不同,主要區別在於該方法無返回值。因此不能通過返回值決定是否終止請求。其主要作用是進行資源的準備工作。
2)postHandle(WebRequest request, ModelMap model)方法,同樣也是在controller之後,檢視返回被渲染之前被呼叫。該方法有兩個引數,WebRequest 物件是用於傳遞整個請求資料的,比如在 preHandle 中準備的資料都可以通過 WebRequest 來傳遞和訪問;
3)afterCompletion(WebRequest request, Exception ex)方法,同樣是在檢視渲染之後呼叫,主要用來進行資源的釋放。
過濾器
Servlet API中提供了一個Filter介面,開發web應用時,如果編寫的Java類實現了這個介面,則把這個java類稱之為過濾器Filter。通過Filter 技術,開發人員可以實現使用者在訪問某個目標資源之前,對訪問的請求和響應進行攔截。
Filter介面中有一個doFilter方法,當我們編寫好Filter,並配置對哪個web資源進行攔截後,WEB伺服器每次在呼叫web資源的service方法之前,都會先呼叫一下filter的doFilter方法,因此,在該方法內編寫程式碼可達到如下目的:
呼叫目標資源之前,讓一段程式碼執行;
是否呼叫目標資源(即是否讓使用者訪問web資源);
呼叫目標資源之後,讓一段程式碼執行。
web伺服器在呼叫doFilter方法時,會傳遞一個filterChain物件進來,filterChain物件是filter介面中最重要的一個對 象,它也提供了一個doFilter方法,開發人員可以根據需求決定是否呼叫此方法,呼叫該方法,則web伺服器就會呼叫web資源的service方 法,即web資源就會被訪問,否則web資源不會被訪問。
過濾器中的方法
init: 程式啟動時,web伺服器將建立Filter的例項物件,並呼叫其init方法,完成物件的初始化 功能;filter物件只會建立一次,init方法也只會執行一次。
doFilter:當訪問web伺服器時對請求進行操作。
destroy:web容器呼叫destroy方法銷燬Filter。destroy方法在Filter的生命週期中僅執行一次。在destroy方法中,可以釋放過濾器使用的資源。
監聽器
監聽web應用,監聽許多資訊的初始化,銷燬,增加,修改,刪除等 。
監聽器物件可以在事情發生前、發生後可以做一些必要的處理。
監聽器的分類
1、ServletContext監聽
ServletContextListener:用於對Servlet整個上下文進行監聽(建立、銷燬)。
ServletContextAttributeListener:對Servlet上下文屬性的監聽(增刪改屬性)。
2、Session監聽
HttpSessionListener介面:對Session的整體狀態的監聽。
HttpSessionAttributeListener介面:對session的屬性監聽。
3、Request監聽
ServletRequestListener:用於對Request請求進行監聽(建立、銷燬)。
ServletRequestAttributeListener:對Request屬性的監聽(增刪改屬性)。
3.常見問題
配置檔案中的多個同樣型別的處理器的執行順序是怎樣的?
4.解決方案
在web.xml中如果配置了多個過濾器,那麼會根據配置檔案的中我們自己宣告的順序來執行;同理多個攔截器的執行順序也是這樣的。
5.編碼實戰
6.擴充套件思考
各自應用場景:
兩者的本質區別:從靈活性上說攔截器功能更強大些,Filter能做的事情,Interceptor都能做,而且可以在請求前,請求後執行,比較靈活。Filter主要是針對URL地址做一個編碼的事情、過濾掉沒用的引數、安全校驗(比較泛的,比如登入狀態之類),太細的話,還是建議用interceptor。Filter只在Servlet前後起作用。而攔截器能夠深入到方法前後、異常丟擲前後等,因此攔截器的使用具有更大的彈性。所以在Spring構架的程式中,優先使用攔截器。
7.參考文獻
連結:https://baike.baidu.com/item/MyBatis/2824918?fr=aladdin
作者:百度百科
連結:https://www.w3cschool.cn/
作者:w3cschool
連結:https://blog.csdn.net/wangyongxia921/article/details/46272813
作者:_Cassie
http://how2j.cn/k/spring/spring-aop/89.html#step5306
作者:how2j
連結:https://www.cnblogs.com/fenglie/articles/4097759.html
作者:fenglie
8.更多討論
問題一:過濾器和攔截器的區別?
①攔截器是基於java的反射機制的,而過濾器是基於函式回撥。
②攔截器不依賴與servlet容器,過濾器依賴與servlet容器。
③攔截器只能對action請求起作用,而過濾器則可以對幾乎所有的請求起作用。
④攔截器可以訪問action上下文、值棧裡的物件,而過濾器不能訪問。
⑤在action的生命週期中,攔截器可以多次被呼叫,而過濾器只能在容器初始化時被呼叫一次。
⑥攔截器可以獲取IOC容器中的各個bean,而過濾器就不行,這點很重要,在攔截器裡注入一個service,可以呼叫業務邏輯。
問題二:過濾器和攔截器的執行順序?
過濾器和攔截器的執行順序:過濾前 - 攔截前 - Action處理 - 攔截後 - 過濾後。攔截器是被包裹在過濾器之中的。
問題三:各自應用場景?
兩者的本質區別:從靈活性上說攔截器功能更強大些,Filter能做的事情,Interceptor都能做,而且可以在請求前,請求後執行,比較靈活。Filter主要是針對URL地址做一個編碼的事情、過濾掉沒用的引數、安全校驗(比較泛的,比如登入狀態之類),太細的話,還是建議用interceptor。Filter只在Servlet前後起作用。而攔截器能夠深入到方法前後、異常丟擲前後等,因此攔截器的使用具有更大的彈性。所以在Spring構架的程式中,優先使用攔截器。
今天的分享就到這裡啦,歡迎大家點贊、轉發、留言、拍磚~