Filter過濾器


Filter概述

Filter是javax.servlet包中的一個接口,一個filter是對客戶請求/響應進行攔截任務的一個對象。Filter調用doFilter()方法,傳送給該方法的FilterConfig ,包含其初始化參數。

Filter的工作流程:

當客戶端發出Web資源的請求時,Web服務器根據應用程序配置文件設置的過濾規則進行檢查,若客戶請求滿足過濾規則,則對客戶請求/響應進行攔截,對請求頭和請求數據進行檢查或改動,並依次通過過濾器鏈,最後把請求/響應交給請求的Web資源處理。請求信息在過濾器鏈中可以被修改,也可以根據條件讓請求不發往資源處理器,並直接向客戶機發回一個響應。當資源處理器完成了對資源的處理後,響應信息將逐級逆向返回。同樣在這個過程中,用戶可以修改響應信息,從而完成一定的任務。
這裏寫圖片描述

多個過濾器同時過濾一個請求時,組成過濾鏈FilterChain,服務器按web.xml中定義過濾器先後順序組成一條鏈,然後執行doFilter()方法。
執行流程:

執行第一個過濾器的chain.doFilter()之前的代碼——>第二個過濾器的chain.doFilter()之前的代碼——>…….——>第n個過濾器的chain.doFilter()之前的代碼——>所請求Servlet的service()方法中的代碼——>所請求的doGet()或doPost()方法中的代碼——>第n個過濾器的chain.doFilter()之後的代碼——>……——>第二個過濾器的chain.doFilter()之後的代碼——>第一個過濾器的chain.doFilter()之後的代碼。

常見過濾器種類

  • Authentication Filters:負責檢查用戶請求,根據請求過濾用戶非法請求。
  • Logging and Auditing Filters:詳細記錄某些用戶請求
  • Image conversion Filters :圖像轉換過濾器
  • Data compression Filters:數據壓縮過濾器
  • Encryption Filters :加密過濾器
  • Tokenizing Filters:標記化過濾器
  • Filters that trigger resource access events :觸發資源訪問事件過濾器
  • XSL/T filters:能改變XML內容
  • Mime-type chain Filter:MIME類型過濾鏈


過濾器生命週期

  • 實例化:Web容器在部署Web應用程序時對所有過濾器進行實例化;
  • 初始化:Web容器回調init()方法;
  • 過濾:當請求路徑匹配過濾器的URL映射,Web容器回調doFilter()方法;
  • Web容器在卸載Web應用程序前回調destroy()方法,回收資源。


創建Filter步驟

  1. 創建實現javax.servlet.Filter接口的類;
  2. 在web.xml中配置Filter
package com.afy.servlet;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;

@WebFilter(filterName="log",urlPatterns={"/hi"})

public class LogFilter implements Filter {

    //FilterConfig可用於訪問Filter的配置信息
    private FilterConfig config;

    @Override
    public void init(FilterConfig config) throws ServletException {
        this.config = config;
    }


    @Override
    public void destroy() {
        this.config = null;
    }

    @Override
    //過濾核心方法
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        //--------以下代碼用於對用戶請求執行預處理--------
        //獲取ServletContext對象,用於記錄日誌
        ServletContext context = this.config.getServletContext();
        long before = System.currentTimeMillis();
        System.out.println("開始過濾.......");
        //將請求轉換成HttpServletRequest請求
        HttpServletRequest hrequest = (HttpServletRequest)request;
        //輸出提示信息
        System.out.println("Filter已經截獲到用戶的請求地址: " + hrequest.getServletPath());
        //Filter只是鏈式地址,請求依然放到目的地址
        chain.doFilter(request, response);
        //------------以下代碼用於對服務器響應執行處後處理-------
        long after = System.currentTimeMillis();
        //輸出提示信息
        System.out.println("過濾結束");
        System.out.println("請求被定位到" + hrequest.getRequestURI() + "所花時間爲:" + (after-before));
    }

}


doFilter()方法可以實現對用戶請求進行預處理,也可以實現對服務器-響應進行後處理,分界線爲是否調用chain.doFilter(),執行該方法前,對用戶請求進行預處理,執行後對服務器進行後處理。

Servlet過濾器API

Servlet過濾器API有3個接口,都在javax.servlet包中,分別是Filter接口、FilterChain接口、FilterConfig接口。

Filter接口定義了init(),doFilter(),destroy()方法

public void init(FilterConfig,filterConfig)
開始使用Servlet過濾服務時,Web容器調用此方法一次,爲服務準備過濾器;需要使用過濾器時調用doFilter(),傳送給次方法的FilterConfig對象,包含Servlet過濾器的初始化參數;

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
過濾器在doFilter()方法中,可以通過它們的方法手機數據,或者給對象添加新的行爲,過濾器通過傳送至該方法的FilterChain參數,調用chain.doFilter()將控制權傳送給下一個過濾器。如果過濾器想要終止請求的處理或得到對響應的完全控制,可以不調用下一個過濾器,而將其重定向到其他頁面。當鏈中的最後一個過濾器調用chain.doFilter()方法時,將運行最初請求的Servlet。

public void destroy()
當doFilter()方法裏的所有線程退出或超時,容器調用此方法。

public interface FilterChain
FilterChain接口有一個方法public void doFilter(ServldtRequest request, ServletResponse response),此方法用於對資源過濾鏈的依次調用,通過FilterChain調用過濾器的下一個過濾器,如果是最後一個過濾器則調用目標資源。

public interface FilterConfig
FilterConfig接口檢索過濾器名,初始化參數和Servlet上下文。有4個方法。

  • public java.lang.String getFilterName()返回web.xml文件中定義該過濾器的名稱。
  • public java.lang.String getInitParameter(String name)返回過濾器初始化參數值的字符串形式,參數不存在則返回null,其中的name是初始化參數名。
  • public java.util.Enumeration getInitParameterNames()以Enumeration形式返回過濾器所有初始化參數值,如果沒有初始化參數,返回爲空。
  • public ServletContext getServletContext()返回調用者所處的Servlet上下文。


    Filter與Servlet近似,它們有相同的生命週期行爲。Filter的doFilter()方法裏多了一個FilterChain的參數,通過該參數可以控制是否放行用戶請求。實際應用中,Filter裏doFilter()方法裏的代碼是從多個Servlet的service()方法裏抽取的通用代碼,通過Filter實現更好的代碼複用。如果系統裏有多個Servlet,這些Servlet都需要進行一些通用出來就,如權限控制、記錄日誌、設置編碼等,這樣Servelet的service方法中有部分代碼會相同,這時可以考慮將這些通用處理放到Filter中完成,而Servlet裏只放特定請求相關的處理就代碼,把通用處理交給Filter完成。

    這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章