一、過濾器 Filter
1. 什么是過濾器?
過濾期正如我們生活中用來過濾東西的東西,泡茶喝,用紗網過濾茶葉一樣。再web中,當我們瀏覽器訪問服務器時候,瀏覽器所發送的請求會先經過過濾器被攔截下來,讓過濾器來執行某些操作。在實際開發中,過濾器的常用用途有登錄驗證、統一編碼處理、過濾敏感字符等等
2. 入門
要創建一個過濾器,只需要創建一個Java類,然后讓過濾器實現Filter接口,然后重寫里面的三個方法:init、doFilter、destroy即可,最后再配置一下攔截路徑即可。
首先,對於inti、destroy方法,他和servlet是一樣的,在服務器加載和銷毀的時候會執行一次,通常inti用來加載資源,而服務器在正常關閉后,Filter對象被銷毀,只執行一次destroy方法,用於釋放資源
對於doFilter,他是在每次請求攔截資源時候,都會執行,所以他是執行多次的。要注意,該方法有三個參數,前兩個我們都很熟悉了,對於第三個參數FilterChain,他是一個接口,在該接口中又定義了doFilter方法。這是咋回事呢?可以這樣理解:過濾器不單只有一個,在Java中就使用了鏈式結構。把所有的過濾器都放在FilterChain里邊,如果符合條件,就執行下一個過濾器(如果沒有過濾器了,就執行目標資源)。
3. 執行流程
- 先執行過濾器
- 執行放行后的資源
- 最后再返回回來執行放行代碼下面的其他代碼
4. 配置攔截路徑
4.1 注解配置方法
若要使用注解方法配置攔截路徑,需要在Filter前面加上@WebFilter()
括號里面的就是攔截路徑,如果只寫攔截路徑,可以不寫參數名,因為默認就是value/urlPattern
,如果還要設置其他參數的話,那么就要加上參數名了。如果想要部分的Web資源進行過濾器過濾則需要指定Web資源的名稱即可。
若要指定過濾器攔截的資源被Servlet容器調用的方式,那么可以設置dispatcherTypes
,有:DispatcherType.REQUEST(默認)、DispatcherType.ERROR、DispatcherType.FROWARD、DispatcherType.INCLUDE、DispatcherType.ASYNC五種方式,分別對應如下:
- REQUEST:默認值。瀏覽器直接請求資源
- FORWARD:轉發訪問資源
- INCLUDE:包含訪問資源
- ERROR:錯誤跳轉資源
- ASYNC:異步訪問資源
4.2web.xml配置方法
在web.xml中,添加如下代碼:filter用於注冊過濾器,如果沒有配置的話,即使實現類Filter接口也沒有用
<filter>
<filter-name>設置一個filter名</filter-name>
<filter-class>要配置的Filter的全類名</filter-class>
<!-- 用於為過濾器指定的初始參數,在init中可以通過filterConfig來獲取 -->
<init-param>
<param-name>word_file</param-name>
<param-value>/WEB-INF/word.txt</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>對應上面的filter名</filter-name>
<url-pattern>設置攔截路徑</url-pattern>
<dispatcher>?指定 Filter 對資源的多種調用方式進行攔截(默認REQUEST)</dispatcher>
<servlet-name>過濾指定的servlet的資源名稱</servlet-name>
</filter-mapping>
5. 多個過濾器(過濾器鏈)的執行順序
- 過濾器1
- 過濾器2
- 過濾器3
- 執行目標資源
- 過濾器3的剩下的代碼
- 過濾器2的剩下的代碼
- 過濾器1的剩下的代碼
過濾器的先后執行順序問題是怎樣的?
- 如果使用的是web.xml配置的話,那么你的``filter-mapping`哪個寫在前面就會先執行哪個過濾器,寫在后面的就會后執行,和filter無關。
- 如果使用的是注解的配置方式的話,那么會比較過濾器的類名,值小的先執行,例如a小於b,所以a過濾器會先執行
6. 過濾器的簡單應用
6.1 禁止瀏覽器緩存
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
// 只有HttpServletResponse才可以設置響應信息,所以我們一般都將他們轉化為Http
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
// 設置禁止緩存
response.setDateHeader("Expires", -1);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
chain.doFilter(request, response);
}
設置之后響應頭為:
6.2 實現自動登錄
6.3 編碼過濾器
- 可以通過實現HTTP ServletRequestWrapper類來增強request對象
6.4 敏感詞匯過濾
- 可以使用動態代理實現敏感詞匯過濾
6.5 壓縮資源過濾器
6.6 HTML轉義過濾器
6.7 緩存數據到內存中
二、監聽器 Listener
什么是監聽器?
監聽器就是⼀個實現特定接⼝的普通java程序,這個程序專⻔⽤於監聽另⼀個java對象的⽅法調
⽤或屬性改變,當被監聽對象發⽣上述事件后,監聽器某個⽅法將⽴即被執⾏。
事件監聽機制
-
事件源:事件發生的對象,即被監聽的對象
-
事件對象:封裝事件源和動作
-
事件監聽器:將事件對象傳入,由開發人員編寫監聽器對象處理事件對象
-
注冊監聽:在事件源上關聯監聽器對象
內置監聽器
在Servlet規范中定義了多種類型的監聽器,它們⽤於監聽的事件源分別 ServletContext,HttpSession和ServletRequest 這三個域對象
Servlet監聽器的注冊不是在事件源上,而是由web容器負責,我們只需要在web.xml中配置好
監聽對象的創建和銷毀
HttpSessionListener、ServletContextListener、ServletRequestListener分別監聽着Session、Context、Request對象的創建和銷毀
- HttpSessionListener(可以⽤來收集在線者信息)
- ServletContextListener(可以獲取web.xml⾥⾯的參數配置)
- ServletRequestListener
監聽對象屬性的變化
ServletContextAttributeListener、HttpSessionAttributeListener、ServletRequestAttributeListener 分別監聽着Context、Session、Request對象屬性的變化
着三個接口都定義了以以下三個方法來處理被監聽對象中的屬性的增加、刪除、替換事件,同一個事件在三個接口中方法名完全相同,只是接受的參數類型不同:
- attributeAdded()
- attributeRemoved()
- attributeReplaced()
監聽Session內的對象
除了上面的6中listener,還有兩種listener監聽Session的對象:HttpSessionBindingListerner和HttpSsessionActivation:
- HttpSessionBindingListener: JavaBean對象可以感知自己被綁定到Session中和從Session中的刪除的事件( 和HttpSessionAttributeListener的作用是差不多的 )
- HttpSessionActivationListener: JavaBend對象可以感知自己被活化和鈍化的事件( 當服務器關閉時, 會將Session的內容保存在硬盤上[鈍化], 當服務器開啟時, 會將Session的內容在硬盤上重新加載[活化] )
想要測試出Session的硬化和鈍化,需要修改Tomcat的配置的。在META-INF下的context.xml⽂件中添加下⾯的代碼:
<Context>
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore" directory="linzeliang"/>
</Manager>
</Context>
監聽器的應用
- 統計網站在線人數
- 監聽Session是否被創建了
- 如果Session創建了, Context域對象的人數的值就+1
- 如果Session被移除了, 那么值就-1
- 自定義Session掃描器
- 監聽Session和Context的創建
- 使用一個容器來裝Session
- 定時掃描容器中的Session,如果長時間沒用就remove
- 在線踢人
- 也是使用容器來裝Session
- 列出所用用戶
- 可以選擇將列出用戶(Session)踢掉, 即刪除Session