聊一聊過(guò)濾器與監(jiān)聽(tīng)器
不少讀者催我寫(xiě)「過(guò)濾器和監(jiān)聽(tīng)器」,于是我就又來(lái)了。
什么是過(guò)濾器?
我們很容易發(fā)現(xiàn),過(guò)濾器可以比喻成一張濾網(wǎng)。我們想想現(xiàn)實(shí)中的濾網(wǎng)可以做什么:在泡茶的時(shí)候,過(guò)濾掉茶葉。那濾網(wǎng)是怎么過(guò)濾茶葉的呢?規(guī)定大小的網(wǎng)孔,只要網(wǎng)孔比茶葉小,就可以實(shí)現(xiàn)過(guò)濾了!
引申在Web容器中,過(guò)濾器可以做:過(guò)濾一些敏感的字符串【規(guī)定不能出現(xiàn)敏感字符串】、避免中文亂碼【規(guī)定Web資源都使用UTF-8編碼】、權(quán)限驗(yàn)證等等等,過(guò)濾器的作用非常大,只要發(fā)揮想象就可以有意想不到的效果
這次的PDF共有「58」頁(yè),PDF涉及到的內(nèi)容:
- 過(guò)濾器入門(mén)和應(yīng)用
- 監(jiān)聽(tīng)器入門(mén)和應(yīng)用
- 幾道簡(jiǎn)單的過(guò)濾器和監(jiān)聽(tīng)器面試題
過(guò)濾器的知識(shí)點(diǎn)
「學(xué)某項(xiàng)技術(shù)之前,首先要知道它能干什么,學(xué)了這項(xiàng)技術(shù)有什么好處,再細(xì)學(xué)」
知道了什么是過(guò)濾器以后,其實(shí)我們學(xué)的東西就不是很多了,感覺(jué)花半天就能學(xué)完了。
首先,我們來(lái)認(rèn)識(shí)一下Filter接口和相對(duì)應(yīng)的doFilter()方法以及它的參數(shù)。
學(xué)過(guò)我之前的「Servlet」教程,對(duì)doFilter()里邊的ServletRequest和ServletResponse應(yīng)該就很了解了,我這里也不贅述了。唯一可能讓人難以理解的就是FilterChain這個(gè)接口。
而FilterChain接口里邊其實(shí)也是一個(gè)doFilter方法。
我們可以這樣理解:過(guò)濾器不單單只有一個(gè),那么我們?cè)趺垂芾磉@些過(guò)濾器呢?在Java中就使用了鏈?zhǔn)浇Y(jié)構(gòu)。把所有的過(guò)濾器都放在FilterChain里邊,如果符合條件,就執(zhí)行下一個(gè)過(guò)濾器(如果沒(méi)有過(guò)濾器了,就執(zhí)行目標(biāo)資源)。
上面的話(huà)好像有點(diǎn)拗口,我們可以想象生活的例子:現(xiàn)在我想在茶杯上能過(guò)濾出石頭和茶葉出來(lái)。石頭在一層,茶葉在一層。所以茶杯的過(guò)濾裝置應(yīng)該有兩層濾網(wǎng)。這個(gè)過(guò)濾裝置就是FilterChain,過(guò)濾石頭的濾網(wǎng)和過(guò)濾茶葉的濾網(wǎng)就是Filter。在石頭濾網(wǎng)中,茶葉是屬于下一層的,就把茶葉放行,讓茶葉的濾網(wǎng)過(guò)濾茶葉。過(guò)濾完茶葉了,剩下的就是茶
對(duì)上面的API了解完了以后,我們?cè)囍约簩?xiě)一個(gè)過(guò)濾器(實(shí)際上就是實(shí)現(xiàn)Filter接口,重寫(xiě)doFilter()方法),然后以注解/xml配置的方式來(lái)部署自己的過(guò)濾器。
隨后看一下FilterChain的執(zhí)行順序是不是自己配置的那樣,再寫(xiě)幾個(gè)常見(jiàn)的過(guò)濾器應(yīng)用就好了,比如說(shuō)「禁止瀏覽器緩存」「實(shí)現(xiàn)自動(dòng)登錄」「編碼過(guò)濾器」「敏感詞過(guò)濾器」「壓縮資源過(guò)濾器」「HTML轉(zhuǎn)義過(guò)濾器」「緩存數(shù)據(jù)」…
工作中用「過(guò)濾器」多嗎?
三歪在工作時(shí)間不長(zhǎng)哈,接觸了好多些系統(tǒng),由我們自己去寫(xiě)「過(guò)濾器」的場(chǎng)景還是不多的。但我覺(jué)得有一點(diǎn)可以好好學(xué)學(xué),就是「責(zé)任鏈模式」。
之前為啥我寫(xiě)了一篇「責(zé)任鏈模式」,其實(shí)就是這個(gè)設(shè)計(jì)模式在系統(tǒng)中用得挺多的,號(hào)稱(chēng)能搞掂if else。
過(guò)濾器其實(shí)也是責(zé)任鏈模式的一種實(shí)現(xiàn),F(xiàn)ilterChain層層往下執(zhí)行,直到最后沒(méi)有過(guò)濾器,就到了「目標(biāo)資源」
什么是監(jiān)聽(tīng)器?
監(jiān)聽(tīng)器就是一個(gè)實(shí)現(xiàn)特定接口的普通Java程序,這個(gè)程序?qū)iT(mén)用于監(jiān)聽(tīng)一個(gè)Java對(duì)象的方法調(diào)用或?qū)傩愿淖儯?dāng)被監(jiān)聽(tīng)對(duì)象發(fā)生上述事件后,監(jiān)聽(tīng)器某個(gè)方法將立即被執(zhí)行。
上面這句話(huà)應(yīng)該也很好理解,比如說(shuō)我有一個(gè)SanWai對(duì)象,里邊有一個(gè)eat()方法。每當(dāng)SanWai.eat()的時(shí)候,我的監(jiān)聽(tīng)器可以監(jiān)聽(tīng)到SanWai.eat()被調(diào)用了,于是我們就可以搞一波邏輯,做別的事了。
- 比如說(shuō),三歪女朋友發(fā)現(xiàn)三歪要吃飯了,于是打電話(huà)讓三歪少吃點(diǎn)。
回到Servlet層面上,我們更多的監(jiān)聽(tīng)的是「Session」「Request」「ServletContext」這幾個(gè)對(duì)象的創(chuàng)建/銷(xiāo)毀/屬性?xún)?nèi)的變化。
針對(duì)監(jiān)聽(tīng)上面的幾個(gè)對(duì)象,我們可以做出一些小例子,比如說(shuō)「統(tǒng)計(jì)網(wǎng)站的在線人數(shù)」「自動(dòng)踢人」「定時(shí)清除Session的值」
監(jiān)聽(tīng)器在工作中用得多嗎?
監(jiān)聽(tīng)器在寫(xiě)業(yè)務(wù)代碼的時(shí)候,同樣也用得不多,我?guī)缀鯖](méi)怎么寫(xiě)過(guò)監(jiān)聽(tīng)器的代碼。
但是理解監(jiān)聽(tīng)器這個(gè)概念我覺(jué)得還是很有必要的。以我的理解,大概可以認(rèn)為「A發(fā)生了變化,B需要依賴(lài)A發(fā)生的變化做出處理」,這就是監(jiān)聽(tīng)器。
有人認(rèn)為,這不就是「事件驅(qū)動(dòng)」嗎?我覺(jué)得也可以那樣理解。
監(jiān)聽(tīng)器和過(guò)濾器再總結(jié)
監(jiān)聽(tīng)器和過(guò)濾器在工作中可能讓我們自己「手寫(xiě)」的概率不是很大,但我覺(jué)得這兩個(gè)技術(shù)還是需要了解的。如果你了解過(guò)Struts2,你就會(huì)發(fā)現(xiàn)Struts2就是用的過(guò)濾器來(lái)實(shí)現(xiàn)很多的功能。監(jiān)聽(tīng)器在Spring源碼里邊也有很多的實(shí)現(xiàn),我覺(jué)得都可以看看。
過(guò)濾器和監(jiān)聽(tīng)器還是需要理解它的思想,這塊對(duì)我們學(xué)習(xí)Spring也是很有幫助的。
現(xiàn)在已經(jīng)工作有一段時(shí)間了,為什么還來(lái)寫(xiě)過(guò)濾器和監(jiān)聽(tīng)器呢,原因有以下幾個(gè):
- 我是一個(gè)對(duì)排版有追求的人,如果早期關(guān)注我的同學(xué)可能會(huì)發(fā)現(xiàn),我的GitHub、文章導(dǎo)航的read.me會(huì)經(jīng)常更換?,F(xiàn)在的GitHub導(dǎo)航也不合我心意了(太長(zhǎng)了),并且早期的文章,說(shuō)實(shí)話(huà)排版也不太行,我決定重新搞一波。
- 我的文章會(huì)分發(fā)好幾個(gè)平臺(tái),但文章發(fā)完了可能就沒(méi)人看了,并且圖床很可能因?yàn)槠脚_(tái)的防盜鏈就掛掉了。又因?yàn)橛泻芏嗟淖x者問(wèn)我:”你能不能把你的文章轉(zhuǎn)成PDF啊?“
- 我寫(xiě)過(guò)很多系列級(jí)的文章,這些文章就幾乎不會(huì)有太大的改動(dòng)了,就非常適合把它們給”持久化“。
































