白銀市建設(shè)局網(wǎng)站王浩百度賬戶代運營
過濾器(Filter)概念總結(jié)
什么是過濾器
過濾器(Filter)是Java Web應(yīng)用中用于統(tǒng)一攔截和處理請求的組件,類似于現(xiàn)實生活中的空氣凈化器或安檢。它通過對請求進(jìn)行前置處理,確保請求符合特定要求。
過濾器的執(zhí)行機(jī)制
- 當(dāng)請求從瀏覽器發(fā)送到Tomcat時,首先會經(jīng)過過濾器,而不是直接到達(dá)Servlet。
- 請求會依次經(jīng)過各個過濾器進(jìn)行處理。每個過濾器可以對請求進(jìn)行檢查、修改等操作。
- 處理完請求后,最終請求會到達(dá)Servlet進(jìn)行業(yè)務(wù)邏輯處理。
- 響應(yīng)則會按照原始路徑逆向通過過濾器返回給瀏覽器。
過濾鏈
過濾器處理請求的過程稱為過濾鏈。請求在過濾鏈中依次被處理,確保只有符合要求的請求才能到達(dá)Servlet。
過濾器的基本概念
- 過濾器是用來對請求和響應(yīng)進(jìn)行處理的組件,可以在請求到達(dá)Servlet之前或響應(yīng)返回給客戶端之前進(jìn)行攔截。
開發(fā)步驟
-
實現(xiàn)Filter接口
- 任何過濾器都需要實現(xiàn)
javax.servlet.Filter
接口。
- 任何過濾器都需要實現(xiàn)
-
實現(xiàn)doFilter方法
doFilter
方法是過濾器的核心,定義了過濾器的具體功能。- 方法參數(shù)包括:
ServletRequest request
:請求對象ServletResponse response
:響應(yīng)對象FilterChain chain
:過濾鏈,用于將請求和響應(yīng)傳遞給下一個過濾器或目標(biāo)Servlet。
-
配置過濾器
- 在
web.xml
文件中進(jìn)行配置,定義過濾器及其作用的URI。 - 使用
<filter>
標(biāo)簽定義過濾器,使用<filter-mapping>
標(biāo)簽指定過濾器攔截的請求URI。
- 在
示例代碼
- 創(chuàng)建項目和包結(jié)構(gòu)
- 實現(xiàn)過濾器
FirstFilter
package com.imooc.filter;import javax.servlet.*;
import java.io.IOException;public class FirstFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.printf("過濾器已生效");filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {}
}
package com.imooc.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/hello")
public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.getWriter().write("<h1>hello servlet</h1>");}
}
過濾器的特性
- 過濾器對象在Web應(yīng)用啟動時被創(chuàng)建且全局唯一。
- 唯一的過濾器對象在并發(fā)環(huán)境中采用“單例多線程”提供服務(wù)。
過濾器的配置形式
在web.xml
中配置過濾器的基本形式如下:
<filter><filter-name>firstFilter</filter-name><filter-class>com.imooc.filter.FirstFilter</filter-class>
</filter><filter-mapping><filter-name>firstFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
配置與注解的選擇總結(jié)
本節(jié)課探討了過濾器的配置形式與注解形式各自的優(yōu)劣,并提供了一些使用建議。
注解形式的優(yōu)勢
- 注解形式的開發(fā)體驗更好,配置和源代碼放在一起,減少在源代碼和配置文件之間來回切換的麻煩。
- 更適合小型敏捷項目,可以快速開發(fā)和迭代。
- 更適合局部功能的設(shè)置,如特定的Servlet,因為Servlet的映射地址通常較為穩(wěn)定,職責(zé)單一,注解可以讓開發(fā)更靈活。
配置形式的優(yōu)勢
- 配置形式更適合大型系統(tǒng),尤其是需要全局過濾的場景,如全局的字符集過濾器等。
- 維護(hù)性更強(qiáng),配置在
web.xml
中可以靈活修改,無需重新編譯代碼。 - 更適合全局應(yīng)用過濾,在真實項目中,過濾器常用于全局性的請求處理。
使用建議
- 全局過濾器(如字符集過濾器):推薦使用配置形式,放在
web.xml
中。 - 局部功能或小范圍設(shè)置(如Servlet):推薦使用注解形式,讓開發(fā)更靈活,增強(qiáng)開發(fā)體驗。
注解形式雖然開發(fā)體驗好,但在全局性應(yīng)用場景下,配置文件形式更具優(yōu)勢。而在局部、單一職責(zé)的場景下,注解則顯得更加適合。
過濾鏈的概念與使用
本節(jié)我們來學(xué)習(xí)一個重要的概念——過濾鏈。過濾鏈顧名思義,就是由過濾器所形成的調(diào)用鏈條。在真實的項目中,過濾器往往不只有一個,當(dāng)一個請求被發(fā)出后由 Tomcat 接收,再轉(zhuǎn)而由 Web APP 來進(jìn)行處理時,首先會經(jīng)過過濾器所形成的執(zhí)行鏈條,依次對請求進(jìn)行過濾處理,最終送達(dá)到 Servlet。在 Servlet 處理后,相應(yīng)的響應(yīng)也會按照原始的路徑反向返回給客戶端。這就是過濾鏈的處理過程。
過濾鏈并不是一個復(fù)雜的概念,只是一種消息傳遞的機(jī)制。但是對于過濾鏈來說,也有一些需要考慮的細(xì)節(jié),比如說哪個過濾器先執(zhí)行,哪個過濾器后執(zhí)行,以及過濾器和過濾器之間該如何設(shè)計。下面我們來看一下關(guān)于過濾鏈的一些開發(fā)注意事項,主要有以下三點:
開發(fā)注意事項
1. 單一職責(zé)原則
每個過濾器應(yīng)該都有單獨的職責(zé)。比如字符集過濾器的職責(zé)非常單一,就是進(jìn)行請求和響應(yīng)的字符集設(shè)置。如果在這個過濾器中額外增加關(guān)于用戶身份的前置過濾,顯然是不合適的。正確的做法是應(yīng)該把這個額外的工作交給一個專用的用戶認(rèn)證過濾器來進(jìn)行。在軟件開發(fā)時,具體的類都要有明確的職責(zé),不要把各種功能混在一起。這樣做可以提高程序的維護(hù)性和可讀性。
2. 過濾器的執(zhí)行順序
過濾器在執(zhí)行過程中,執(zhí)行順序是以 filter-mapping
前后書寫順序來決定的。對于一個請求,如果被多個過濾器進(jìn)行攔截,那么這些過濾器的執(zhí)行順序?qū)⒁?filter-mapping
在配置文件中的前后順序依次執(zhí)行。
3. 過濾器鏈的傳遞
如果沒有特殊原因,不要中斷過濾鏈。在過濾器的 doFilter
方法最后要增加 chain.doFilter
,讓請求向后進(jìn)行傳遞,最終送達(dá)給 Servlet 進(jìn)行處理。如果沒有調(diào)用這句話,將意味著過濾鏈在當(dāng)前就被處理完,請求會立即返回。
監(jiān)聽器與過濾器的區(qū)別及實現(xiàn)
監(jiān)聽器(Listener)
-
概念:
- 監(jiān)聽器是標(biāo)準(zhǔn) J2EE Servlet 模塊下的組件,用于監(jiān)控外部應(yīng)用中的內(nèi)置對象,如
ServletContext
、HttpSession
和ServletRequest
。 - 監(jiān)聽器可以自動觸發(fā)指定的功能代碼,對 Web 對象進(jìn)行監(jiān)聽,屬于被動觸發(fā)。
- 監(jiān)聽器是標(biāo)準(zhǔn) J2EE Servlet 模塊下的組件,用于監(jiān)控外部應(yīng)用中的內(nèi)置對象,如
-
實現(xiàn)與配置:
- 通過實現(xiàn)特定的接口(如
ServletContextListener
、HttpSessionListener
、ServletRequestListener
)來定義監(jiān)聽邏輯。 - 每個接口都包含多個必須實現(xiàn)的方法,這些方法對應(yīng)于不同對象的創(chuàng)建和銷毀事件。
- 在
web.xml
文件中配置監(jiān)聽器時,需要添加<listener>
標(biāo)簽,并指定監(jiān)聽器的全類名。
- 通過實現(xiàn)特定的接口(如
過濾器(Filter)
-
概念:
- 過濾器是 Servlet 規(guī)范中的一個組件,用于攔截客戶端的請求和服務(wù)器的響應(yīng)。
- 它屬于主動行為,可以對請求和響應(yīng)進(jìn)行預(yù)處理或后處理。
-
主要用途:
- 進(jìn)行請求和響應(yīng)的內(nèi)容檢查和處理。
- 實現(xiàn)認(rèn)證、日志記錄、字符編碼轉(zhuǎn)換等功能。
監(jiān)聽器與過濾器的區(qū)別
-
觸發(fā)機(jī)制:
- 監(jiān)聽器是被動觸發(fā),當(dāng)特定事件(如對象的創(chuàng)建或銷毀)發(fā)生時自動執(zhí)行相應(yīng)的代碼。
- 過濾器是主動行為,可以對請求和響應(yīng)進(jìn)行攔截和處理。
-
應(yīng)用場景:
- 監(jiān)聽器適用于在對象狀態(tài)改變時(如對象創(chuàng)建或銷毀)執(zhí)行特定操作。
- 過濾器適用于對請求和響應(yīng)內(nèi)容進(jìn)行檢查和處理。
-
配置方式:
- 監(jiān)聽器需要在
web.xml
文件中配置<listener>
標(biāo)簽。 - 過濾器需要在
web.xml
文件中配置<filter>
標(biāo)簽,并指定攔截的 URL 模式。
- 監(jiān)聽器需要在
過濾器(Filter)和監(jiān)聽器(Listener)的區(qū)別
1. 過濾器(Filter):主動檢查
過濾器就像一個門衛(wèi),每當(dāng)有人進(jìn)出時,它都會主動檢查每個人的證件和包裹。它負(fù)責(zé)對每一次進(jìn)出的請求進(jìn)行攔截和處理,不管你進(jìn)來做什么,它都會主動檢查。
生活中的例子:
- 門口安檢:在進(jìn)入一個活動場所之前,安檢人員會主動檢查你的背包和身份。這就是一個典型的過濾器例子。無論你是參觀還是工作,每個人都要先經(jīng)過安檢。
- 水過濾器:當(dāng)自來水流過水過濾器時,它會主動將水中的雜質(zhì)過濾掉,不管水是從哪來,最終流向哪里,只要經(jīng)過水過濾器,它都會主動過濾。
編程中的應(yīng)用:
- 在每次網(wǎng)頁請求時,過濾器可以檢查用戶是否登錄。如果沒有登錄,就會將用戶重定向到登錄頁面。
- 它可以在用戶提交數(shù)據(jù)時,檢查數(shù)據(jù)是否合法(比如是否包含敏感詞匯),然后再決定是否繼續(xù)處理請求。
總結(jié):過濾器總是會主動在每一次請求到達(dá)服務(wù)器之前攔截并處理,所有請求都要經(jīng)過它的“檢查”。
2. 監(jiān)聽器(Listener):被動反應(yīng)
監(jiān)聽器就像一個在教室后面坐著的老師,他會觀察學(xué)生的狀態(tài)變化,比如誰進(jìn)教室了、誰出去了,但他不會主動干涉每個學(xué)生的行為,只有當(dāng)學(xué)生做出某些動作(比如舉手提問、出教室)時,老師才會有反應(yīng)。
生活中的例子:
- 運動感應(yīng)燈:當(dāng)你走進(jìn)房間時,感應(yīng)燈會亮起。燈不會主動找你,而是等著你進(jìn)入感應(yīng)范圍,它才會被動地亮起。
- 火警報警器:當(dāng)房間里有煙霧時,報警器會被動地響起。它平時不會主動檢查每一個角落,而是等煙霧出現(xiàn)時才會被觸發(fā)。
編程中的應(yīng)用:
- 當(dāng)用戶第一次訪問網(wǎng)站時,
HttpSessionListener
會記錄用戶的會話信息。 - 當(dāng)用戶退出登錄時,
HttpSessionListener
會被觸發(fā)來清理用戶的會話信息。 - 當(dāng)應(yīng)用啟動時,
ServletContextListener
會被觸發(fā),用來初始化一些資源。
總結(jié):監(jiān)聽器不會主動干涉每一個請求或動作,它只在某些特定事件發(fā)生時(如對象的創(chuàng)建、銷毀)被動地反應(yīng)。
3. 兩者的根本區(qū)別:
-
作用對象不同:過濾器作用于“請求和響應(yīng)”的流轉(zhuǎn)過程,而監(jiān)聽器作用于“對象的生命周期”。
- 過濾器:對所有的請求和響應(yīng)進(jìn)行處理,主動決定是否放行、修改請求/響應(yīng)內(nèi)容。
- 監(jiān)聽器:監(jiān)聽特定事件的發(fā)生,被動響應(yīng)這些事件,如會話創(chuàng)建、銷毀等。
-
觸發(fā)時機(jī)不同:
- 過濾器在每次請求到來時都會被主動調(diào)用處理。
- 監(jiān)聽器在特定事件(如會話創(chuàng)建、銷毀、上下文初始化等)發(fā)生時才會被動觸發(fā)。