過濾器是個可重用的(Resuable)元件,可以轉換對資源的請求,也可以轉換回應的內容(過濾器並不負責建立回應內容)。
過濾器通常作為一個服務(Service)加入至應用程式之中,即時地為應用程式增加功能,但不用修改原有的應用程式,在不需要使用服務時,可以直接將過濾器從應用程式抽離,而不用修改原應用程式。過濾器可以實現的服務以下有幾個例子:
- 效能量測 - 例如請求與回應之間的時間差。 
- 請求內容的過濾、轉換 - 特定字元的過濾、標頭、請求參數的轉換等。 
- 使用者的驗證 - 驗證使用者是否登入、是否具備某種身份、是否來目某些區域。 
- 資源存取限制 - 根據使用者等資訊,確認其是否可存取某些資源。 
- 回應的加工 - 針對回應作字元轉換、資料壓縮等動作。 
Servlet╱JSP 提供了過濾器機制讓你實作這些元件服務,而就如下圖所示的,你可以視需求抽換過濾器或調整過濾器的順序,也可以針對不同的 URL 套用不同的過濾器。甚至在不同的 Servlet 間請求轉發或包括時套用過濾器。
正如其名稱所示,過濾器概念上就像個濾網,需要時在某些資源存取前、回應前加上濾網,不需要時可直接將濾網拿掉。
在 Servlet╱JSP 中要實作過濾器,在 Servlet 4.0 之前,主要是實作 Filter 介面。Filter 介面定義了三個實作方法:init()、doFilter() 與 destroy()。
package javax.servlet;
import java.io.IOException;
public interface Filter {
    public default void init(FilterConfig filterConfig) throws ServletException {}
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException;
    public default void destroy() {}
}
在 Servlet 4.0 中,由於是基於 Java SE 8,因此 Filter 的 init() 與 destroy() 運用的預設方法實作,然而方法內容為空,這省去在 Servlet 3.1 或更早版本中,實作 Filter 時,即使不需要定義初始或銷毀動作,也必須定義 init() 與 destroy() 的麻煩。
Filter 介面在定義上與 Servlet 介面很類似,同樣都有 init() 與 destroy() 方法,除了 Filter 介面的 init() 方法上的參數是 FilterConfig,而 doFilter() 多了一個 FilterChain 參數。
FilterConfig 類似於 Servlet 介面 init() 方法參數上的 ServletConfig,FilterConfig 為實作 Filter 介面的類別上標註或 web.xml 中過濾器定義的代表物件。如果你在定義過濾器時有設定初始參數,則可以透過 FilterConfig 的 getInitParameter() 方法來取得初始參數。
Filter 介面的 doFilter() 方法則類似於 Servlet 介面的 service() 方法。當請求來到容器,而容器發現呼叫 Servlet 的 service() 方法前,可以套用某過濾器時,就會呼叫該過濾器的 doFilter() 方法。你就是在 doFilter() 方法中,進行 service() 方法的前置處理,而後決定是否呼叫 FilterChain 的 doFilter()方法。
如果呼叫了 FilterChain 的 doFilter() 方法,就會執行下一個過濾器,如果沒有下一個過濾器了,就呼叫請求目標 Servlet 的 service() 方法。如果因為某個情況(例如使用者沒有通過驗證)而沒有呼叫 FilterChain 的 doFilter(),則請求就不會繼續交給接下來的過濾器或目標 Servlet,這時就是所謂的攔截請求(從 Servlet 的觀點來看,它根本不知道瀏覽器有發出請求)。
FilterChain 的 doFilter() 實作,概念上類似以下:
Filter filter = filterIterator.next();
if(filter != null) {
    filter.doFilter(request, response, this);
} 
else {
    targetServlet.service(request, response);
}
在陸續呼叫完 Filter 實例的 doFilter() 仍至 Servlet 的 service() 之後,流程會以堆疊順序返回,所以在 FilterChain 的 doFilter() 執行完畢後,就是你可以針對 service() 方法作後續處理的時機。
// service() 前置處理
chain.doFilter(request, response);
// service() 後置處理
你只需要知道 FilterChain 執行後會以堆疊順序返回即可。在實作 Filter 介面時,不用理會這個 Filter 前後是否有其他 Filter,應該將之作為一個獨立的元件設計,是否採用 Filter,都不應影響應用程式的基本行為。
如果在呼叫 Filter 的 doFilter() 期間,因故丟出 UnavailableException,此時不會繼續下一個 Filter,容器可以檢驗例外的 isPermanent(),如果不是 true,則可以在稍後重試 Filter。

