接近尾聲,還來點實用的技術活兒——過濾器的威力!
124、與servlet非常類似,過濾器就是Java組件,請求發送到servlet之前,可以用過濾器截獲和處理請求,另外servlet結束工作之後,在響應發回給客戶之前,可以用過濾器處理響應。(P672);
125、過濾器是模塊化的,而且可以在DD中配置,容器根據DD中聲明來確定何時調用過濾器。(P672~673);
126、過濾器不知道誰來調用它們,也不知道過濾器鏈中下一個是誰!(675);
127、過濾器的生命週期:
首先要有一個init();
真正的工作在doFilter(ServletRequest req, ServletResponse rsp, FilterChain chain)中完成;
最後來個destroy()。
128、過濾器可以應用於直接來自客戶的請求,這當然很棒。但是如果請求來自轉發或包含、請求分派和/或錯誤處理器呢?
Servlet規範2.4提供瞭解決辦法。(P679);
129、過濾器聲明規則:
1)必須要有<filter-name>;
2)必須要有<url-pattern>或<servlet-name>元素其中之一;
3)可以有0~4個<dispatcher>元素;
4)REQUEST值表示對客戶請求啓用過濾器。如果沒有指定<dispatcher>元素,則默認爲REQUEST;
5)INCLUDE值表示對由一個include()調用分派來的請求啓用過濾器;
6)FORWARD值表示對由一個forward()調用分派來的請求啓動過濾器;
7)ERROR值表示對錯誤處理器調用的資源啓動過濾器。
(P679too);
130、Rachel這樣介紹doFilter()方法中代碼的基本結構——首先,完成與請求相關的工作,然後調用chain.doFilter(),最後,當Servlet(以及鏈中當前過濾器之後的所有其他過濾器)工作結束,而且控制返回到原先的doFilter()方法時,可以對響應在做點工作。(P682);
131、
public void doFilter(request, response, chain){
//請求處理放在這裏
chain.doFilter(request, response);
//這裏完成壓縮邏輯
}
chain.doFilter()調用返回,過濾器希望拿到輸出,並開始處理點什麼……不過,已經太晚了!輸出已經發送給客戶!容器並沒有爲過濾器把輸出緩存起來。等到過濾器自己的doFilter()方法至於(概念)棧的棧頂時,過濾器再想影響輸出已爲時已晚。
(P683);
132、建立一個自己的響應實現,並把它通過chain.doFilter()調用傳遞到Servlet。而且這個定製響應實現還必須包含一個定製的輸出流(處理),因爲這是我們的目標,在Servlet寫輸出之後並且在輸出返回給客戶之前,過濾器就能拿到這個輸出。(P685, 689);
133、包裝器包裝了實際的請求或響應對象,而且調用委託給(傳給)實際的對象,還允許你對定製請求或響應做所需的額外處理。(P687);