過(guò)濾器(Filter):
能夠完成篩選不需要數(shù)據(jù)的工具(東西).
1.什么是過(guò)濾器
生活中:凈水器,香煙過(guò)濾嘴,濾紙,丈母娘,收費(fèi)站等.------->單向的.
Web中:過(guò)濾器其實(shí)就是服務(wù)端的一個(gè)程序(程序的最小單元就是類).
在Web開(kāi)發(fā)中,過(guò)濾器其實(shí)就是一個(gè)Web組件(Servlet/Filter/Listener),其實(shí)就是一個(gè)特殊的類.
一個(gè)類實(shí)現(xiàn)javax.servlet.Servlet接口:--->Servlet類.
一個(gè)類實(shí)現(xiàn)javax.servlet.Filter接口:----->Filter類.
2.過(guò)濾器的作用:
過(guò)濾器可以對(duì)所有的請(qǐng)求或者響應(yīng)做攔截操作.
- 1:以常規(guī)的方式調(diào)用資源(Servlet/JSP);
- 2:利用修改過(guò)的請(qǐng)求信息調(diào)用資源;
- 3:調(diào)用資源之后,但在響應(yīng)到客戶端之前,對(duì)響應(yīng)做出修改;
- 4:阻止當(dāng)前資源調(diào)用,代之轉(zhuǎn)到其他資源.
Filter開(kāi)發(fā)和使用
過(guò)濾器的開(kāi)發(fā)和Servlet非常相似:(類比學(xué)習(xí))
1.開(kāi)發(fā)Servlet:
1):自定義一個(gè)類(XxxServlet),實(shí)現(xiàn)于javax.servlet.Servlet接口(繼承于HttpServlet類).
2):在web.xml中做配置,告訴Tomcat來(lái)幫我管理這一個(gè)類(負(fù)責(zé)了該類的生命周期).:@WebServlet("/xxx")
<servlet>
<servlet-name>XxxServlet</servlet-name>
<servlet-class>XxxServlet類的全限定名</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>XxxServlet</servlet-name>
<!--向外暴露一個(gè)資源名稱,目的:讓客戶端通過(guò)該資源名稱來(lái)訪問(wèn)服務(wù)端對(duì)應(yīng)的一個(gè)Servlet-->
<url-pattern>/xxx</url-pattern>
</servlet-mapping>
2.開(kāi)發(fā)Filter:
1):自定義一個(gè)類(XxxFilter,Xxx表示功能名),實(shí)現(xiàn)于javax.servlet.Filter接口.
2):在web.xml中做配置,告訴Tomcat來(lái)幫我管理這一個(gè)類(負(fù)責(zé)了該類的生命周期).:@WebFilter("/hello.jsp")
<filter>
<filter-name>XxxFilter</filter-name>
<filter-class>XxxFilter類的全限定名</filter-class>
</filter>
filter-mapping>
<filter-name>XxxFilter</filter-name>
<!--表示:當(dāng)前Filter只對(duì)哪些資源做過(guò)濾/攔截操作,只對(duì)hello.jsp做攔截-->
<url-pattern>/hello.jsp</url-pattern>
</filter-mapping>
3.Filter的生命周期方法:
- 1):void init(FilterConfig config): 初始化方法
- 2):void doFilter(ServletRequest request, ServletResponse response, FilterChain chain):執(zhí)行過(guò)濾的方法(每一次請(qǐng)求都會(huì)執(zhí)行過(guò)濾)
- 3):void destroy():銷毀方法
執(zhí)行的流程:
在啟動(dòng)Tomcat服務(wù)器的時(shí)候,就會(huì)執(zhí)行構(gòu)造器和init方法.
構(gòu)造器--->init方法 -----> ( doFilter方法 )N次------->destroy方法
chain:鏈,鏈條,多個(gè)鏈的節(jié)點(diǎn)組合而成.
FilterChain:過(guò)濾器鏈,多個(gè)過(guò)濾器按照一定的順序排列在一起. FilterChain.doFilter(req,resp):放行(放行給下一個(gè)Filter或資源)
4.Filter映射細(xì)節(jié):
-
1):多個(gè)Filter共存的時(shí)候,攔截的先后順序由誰(shuí)來(lái)決定?
由<filter-mapping>的配置先后順序來(lái)決定. -
2):Filter的對(duì)哪些資源做過(guò)濾.
<url-pattern>被過(guò)濾的資源名稱</url-pattern>
方式 | 作用域 |
---|---|
<url-pattern>/hello.jsp</url-pattern> | 只對(duì)/hello.jsp做過(guò)濾. |
<url-pattern>/*</url-pattern> | 對(duì)所有的資源做過(guò)濾操作. |
<url-pattern>/system/*</url-pattern> | 只對(duì)以/system/打頭的資源做過(guò)濾. |
<url-pattern>*.do</url-pattern> | 只對(duì)以.do結(jié)尾的資源做過(guò)濾 |
-
3):可以通過(guò)<init-param>元素來(lái)給當(dāng)前Filter配置初始化參數(shù).
通過(guò)FilterConifg對(duì)象.getInitParameter(String name)來(lái)獲取初始化參數(shù). -
4):Servlet,Filter,Listener都屬于Web組件.
一般的,先配置監(jiān)聽(tīng)器,再配置過(guò)濾器,最后配置Servlet. - 5):<filter-mapping>中的子元素<dispatcher>表示對(duì)哪些操作執(zhí)行過(guò)濾.
<!-- 缺省情況:REQUEST -->
<dispatcher>REQUEST</dispatcher>
<!-- 對(duì)請(qǐng)求轉(zhuǎn)發(fā)做攔截 -->
<dispatcher>FORWARD</dispatcher>
<!-- 對(duì)請(qǐng)求包含做攔截 -->
<dispatcher>INCLUDE</dispatcher>
<!-- 出錯(cuò)之后再跳轉(zhuǎn)到全局的結(jié)果視圖之前做攔截 -->
<dispatcher>ERROR</dispatcher>
請(qǐng)求編碼過(guò)濾器:CharacterEncodingFilter
上述編碼過(guò)濾器,沒(méi)問(wèn)題.但是卻把字符編碼寫死了.
解決方案:把字符編碼作為Filter的初始化參數(shù)來(lái)配置.
登錄驗(yàn)證過(guò)濾器:CheckLoginFilter
屏蔽敏感字過(guò)濾器:ContentFilter
上圖在Servlet類中調(diào)用了FilterUtil的filter方法,完成對(duì)參數(shù)
字符串的敏感字過(guò)濾功能.
從正確與否上分析,沒(méi)問(wèn)題.但是,違背了責(zé)任分類的原則.
解決方案:使用過(guò)濾器來(lái)解決.
上述方式,可以完成敏感字過(guò)濾,但是改變了獲取請(qǐng)求參數(shù)的機(jī)制.放棄.
我們需要解決的問(wèn)題是啥:敏感字過(guò)濾.
為什么需要做這件事情:在原生的HttpServletRequest中的getParameter方法不支持敏感字過(guò)濾.
所以,得出結(jié)論,我們需要完成的: 讓請(qǐng)求對(duì)象中的getParameter方法擁有敏感字過(guò)濾的功能.
目標(biāo):在不改變?cè)蓄惖幕A(chǔ)之上,對(duì)某一個(gè)方法做增強(qiáng).
解決方案:
1):繼承方式,覆蓋需要增強(qiáng)的方法.------->子類出現(xiàn)爆炸式增強(qiáng).
2):組合方式.--->包裝設(shè)計(jì)模式(裝飾設(shè)計(jì)模式:decorator)
裝飾設(shè)計(jì)模式的作用:在不改變?cè)蓄惖幕A(chǔ)之上,對(duì)某一個(gè)對(duì)象做增強(qiáng).
IServletRequerst接口: 模擬 ServletRequest接口.
DefaultServletRequestImpl類: 模擬 ServletRequest接口的實(shí)現(xiàn)類.
提供String getParameter(String name):并返回一個(gè)固定的值.
監(jiān)聽(tīng)器
1.事件驅(qū)動(dòng)編程:
簡(jiǎn)單地說(shuō)就是你點(diǎn)什么按鈕(即產(chǎn)生什么事件),電腦執(zhí)行什么操作(即調(diào)用什么函數(shù))空民。
事件驅(qū)動(dòng)編程中核心對(duì)象:
1):事件源:誰(shuí)發(fā)出事件通知糕伐,發(fā)出消息;也就是事件主體,比如按鈕凤瘦;
2):事件名稱:發(fā)出什么樣的通知的名稱承桥,比如鼠標(biāo)到我頭上了漆魔,我被別人點(diǎn)了一下硝全;
3):事件響應(yīng)函數(shù):誰(shuí)對(duì)這個(gè)這個(gè)事件感興趣,當(dāng)這個(gè)事件發(fā)生時(shí)要執(zhí)行什么樣的操作抄腔;
4):事件對(duì)象:一般來(lái)說(shuō)瓢湃,當(dāng)事件發(fā)生時(shí),會(huì)產(chǎn)生一個(gè)描述該事件的具體對(duì)象妓柜,包含事件相關(guān)信息箱季。
調(diào)戲事件: 某一天,在大街上,張三看到一個(gè)美女,很美,很美,在美女的臉上點(diǎn)擊了一下,美女給了張三一巴掌.
2.Web常見(jiàn)監(jiān)聽(tīng)器:
監(jiān)聽(tīng)request,session,ServletContext對(duì)象.
1):監(jiān)聽(tīng)作用域?qū)Φ膭?chuàng)建和銷毀.
ServletRequestListener:
HttpSessionListener:
ServletContextListener:監(jiān)聽(tīng)服務(wù)器的啟動(dòng)和關(guān)閉.
2):監(jiān)聽(tīng)作用域?qū)ο蟮膶傩缘奶砑?刪除/替換操作.(attributeAdded/attributeRemoved/attributeReplaced)
ServletRequestAttributeListener:
HttpSessionAttributeListener:
ServletContextAttributeListener:
開(kāi)發(fā)監(jiān)聽(tīng)器:對(duì)哪一種事件感興趣,就實(shí)現(xiàn)哪一個(gè)事件對(duì)應(yīng)的接口.
監(jiān)聽(tīng)器沒(méi)有自己的初始化參數(shù),只能使用全局的初始化參數(shù).
<context-param>
<param-name></param-name>
<param-value></param-value>
</context-param>