Filter : 過濾請求和響應
filter物件可以改變請求和響應的頭資訊和內容資訊。過濾器和web元件的不同之處在於,過濾器通常不會自行建立響應。作為替代,過濾器提供附加到任意型別的web資源的功能。因此,過濾器不該對要過濾的web資源有任何依賴。這樣,它可以由多種web資源組成。
過濾器可以執行的主要任務如下:
- 查詢請求並採取響應措施
- 組織請求-響應對的進一步傳遞
- 修改請求頭和資料。你可以通過設定請求的自定義版本來完成此操作。
- 修改響應頭和資料。你可以通過設定響應的自定義版本來完成此操作。
- 與web資源相互作用
應用程式的過濾器包含認證、日誌、圖片轉換、資料壓縮、資料加密、標記流、xml轉換等。
你可以給一個web資源配置0-多個過濾器,並且可以自定義過濾器的順序。過濾器鏈在包含此元件的web資源部署時指定,並且在web容器載入的時候例項化。
編寫filter程式
filtering api定義在javax.servlet包中的Filter, FilterChain, and FilterConfig介面中。你可以通過實現Filter介面定義一個過濾器。
使用@WebFilter註解在web程式中定義過濾器。這個註解作用在類上,並且包含過濾器的元資料。過濾器註解必須定義至少一個url匹配,通過使用z註解的urlPatterns或value屬性完成這個操作。所有其他的屬性都是可選的,有預設設定。當只有一個url規則時使用value註解;當有多個url規則或需要自定義屬性時使用urlPatterns註解。
使用@WebFilter 註解的類必須實現 javax.servlet.Filter 介面。
要將配置資料新增到過濾器中,可以使用@WebFilter註解的initParams屬性。initParams屬性包含一個 @WebInitParam 註解。下面的程式碼片段定義了一個過濾器,定義了一個初始化引數:
import javax.servlet.Filter; import javax.servlet.annotation.WebFilter; import javax.servlet.annotation.WebInitParam; @WebFilter(filterName = "TimeOfDayFilter", urlPatterns = {"/*"}, initParams = { @WebInitParam(name = "mood", value = "awake")}) public class TimeOfDayFilter implements Filter { ...
Filter介面的最重要的方法是doFilter,這個方法可以執行下列操作:
- 核查請求頭
- 定製請求物件,如果過濾器想要修改請求頭或資料
- 定製響應物件,如果過濾器想要修改響應頭或資料
- 呼叫過濾器鏈的下一個實體。如果當前過濾器是過濾器鏈的最後一個過濾器,並且結束目標是web資源或靜態資源,下一個實體是鏈末端的資源;否則,下一個實體是war定義的過濾器。過濾器通過呼叫chain物件的doFilter方法呼叫下一個實體,傳入呼叫它的請求、響應或它建立的包裝版本。換種說法是,filter可以通過不呼叫下一個實體來阻塞請求。在後一種情況下,過濾器負責填充響應。
- 在呼叫下一個實體後核查響應頭
- 丟擲一個錯誤指示執行流程中的錯誤
執行doFilter,你必須實現init和destroy方法。init方法在web容器例項化的時候呼叫;如果你想給filter傳入初始化引數,可以通過傳入init方法的FilterConfig引數獲取它們。
編寫自定義請求和響應程式碼
過濾器有多種方式去修改請求和響應。例如,一個過濾器可以向請求新增一個引數或者在響應中插入資料。
過濾器修改響應必須在響應返回客戶端之前捕獲響應。為此, 您將一個替代流傳遞給生成響應的servlet。備用流阻止servlet在完成時關閉原始響應流,並允許過濾器修改servlet的響應。
要將此替換流傳遞給servlet,過濾器會建立一個響應包裝器,它會覆蓋getWriter或getOutputStream方法以返回此替換流。這個包裝器通過過濾器鏈doFilter方法傳遞。包裝器方法預設呼叫包裝的請求或響應物件。
重寫請求方法,你包裝的請求必須繼承ServletRequestWrapper或HttpServletRequestWrapper。重寫響應方法,你的響應必須繼承ServletResponseWrapper or HttpServletResponseWrapper。
指定過濾器對映
web容器使用請求對映決定給web資源應用具體的過濾器。過濾器對映使用名稱對映一個過濾器到web元件或者使用url規則匹配到web資源。過濾器按照war中定義的順序執行。您可以使用NetBeans IDE或使用XML手動編寫列表來為其部署描述符中的WAR指定過濾器對映列表。
如果你想記錄每一個到web應用的請求,你可以將過濾器對映到url規則“/”。
可以對映filter到一個或多個web資源,當然你也可以給一個web資源對映多個filter。參見下圖,F1對映到S1、S2、S3,F2對映到S2,F3對映到S1、S2.
再次強調,filter chain是傳入filter的doFilter方法的一個引數。該鏈通過過濾器對映間接生成。鏈中的過濾器順序與過濾器對映在Web應用程式部署描述符中的顯示順序相同。當一個過濾器對映到S1,web容器呼叫F1的doFilter方法。S1的過濾器鏈中每個過濾器的doFilter方法由鏈中的前一個過濾器通過chain.doFilter方法呼叫。因為S1的過濾器鏈包含過濾器F1和F3,所以F1對chain.doFilter的呼叫會呼叫過濾器F3的doFilter方法。 當F3的doFilter方法完成時,控制返回F1的doFilter方法。
通過NetBeans IDE定義請求對映
- 在Project節點展開應用程式
- 展開Project節點下的Web Pages and WEB-INF節點
- 雙擊web.xml
- 點選編輯視窗最上方的Filters
- 展開編輯視窗的Servlet Filters節點
- 點選Add Filter Element 新增filter與web資源的url對映關係
- 在新增servlet filter介面,填寫filtername
- 點選Browse定位filter適用的servlet
- 點選ok
- 要約束過濾器應用於請求的方式,步驟如下:
a. 展開Filter Mappings節點
b. 從filterlist中選擇一個filter
c. 點選add
d. 在新增對映彈窗,需要選擇一個轉發型別:
- REQUEST:只對映直接從客戶端過來的請求
- ASYNC:只對映直接從客戶端過來的的非同步async請求
- FORWARD:只有當請求被轉發到元件時
- INCLUDE : 僅當請求由已包含的元件處理時
- ERROR:僅在使用錯誤頁面機制處理請求時
通過選擇多個排程程式型別,可以指示過濾器應用於上述情況的任意組合。 如果未指定型別,則預設選項為REQUEST