程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Servlet過濾器,servlet

Servlet過濾器,servlet

編輯:JAVA綜合教程

Servlet過濾器,servlet


一、Filter的介紹及使用

什麼是過濾器?

與Servlet相似,過濾器是一些web應用程序組件,可以綁定到一個web應用程序中。但是與其他web應用程序組件不同的是,過濾器是"鏈"在容器的處理過程中的。這就意味著它們會在servlet處理器之前訪問一個進入的請求,並且在外發響應信息返回到客戶前訪問這些響應信息。這種訪問使得過濾器可以檢查並修改請求和響應的內容。

過濾器適用於那些地方?

l  為一個web應用程序的新功能建立模型(可被添加到web應用程序中或者從web應用程序中刪除而不需要重寫基層應用程序代碼);

l  向過去的代碼添加新功能。

過濾器放在容器結構的什麼位置?

過濾器放在web資源之前,可以在請求抵達它所應用的web資源(可以是一個Servlet、一個Jsp頁面,甚至是一個HTML頁面)之前截獲進入的請求,並且在它返回到客戶之前截獲輸出請求。Filter:用來攔截請求,處於客戶端與被請求資源之間,目的是重用代碼。Filter鏈,在web.xml中哪個先配置,哪個就先調用。在filter中也可以配置一些初始化參數。

Java中的Filter 並不是一個標准的Servlet ,它不能處理用戶請求,也不能對客戶端生成響應。 主要用於對HttpServletRequest 進行預處理,也可以對HttpServletResponse 進行後處理,是個典型的處理鏈。 

Filter 有如下幾個用處:

l  在HttpServletRequest 到達Servlet 之前,攔截客戶的HttpServletRequest 。 

l  根據需要檢查HttpServletRequest ,也可以修改HttpServletRequest 頭和數據。 

l  在HttpServletResponse 到達客戶端之前,攔截HttpServletResponse 。 

l  根據需要檢查HttpServletResponse ,可以修改HttpServletResponse 頭和數據。

Filter 有如下幾個種類:

l  用戶授權的Filter: Filter 負責檢查用戶請求,根據請求過濾用戶非法請求。 

l  日志Filter: 詳細記錄某些特殊的用戶請求。 

l  負責解碼的Filter: 包括對非標准編碼的請求解碼。 

l  能改變XML 內容的XSLTFilter 等。 

一個Filter 可負責攔截多個請求或響應:一個請求或響應也可被多個請求攔截。 

創建一個Filter 只需兩個步驟: 
(1)創建Filter 處理類: 

(2)在web.xml 文件中配置Filter 。 
創建Filter 必須實現javax.servlet.Filter 接口,在該接口中定義了三個方法。 
• void init(FilterConfig config): 用於完成Filter 的初始化。 
• void destroy(): 用於Filter 銷毀前,完成某些資源的回收。 
• void doFilter(ServletRequest request, ServletResponse response,FilterChain chain): 實現過濾功能,該方法就是對每個請求及響應增加的額外處理。 

過濾器Filter也具有生命周期:init()->doFilter()->destroy(),由部署文件中的filter元素驅動。在servlet2.4中,過濾器同樣可以用於請求分派器,但須在web.xml中聲明,<dispatcher>INCLUDE或FORWARD或REQUEST或ERROR</dispatcher>該元素位於filter-mapping中。 

Filter常用的場景:

一個實例

首先來看一下web.xml的配置:

   

 <!-- 請求url日志記錄過濾器 -->    

    <filter>    
        <filter-name>logfilter</filter-name>    
        <filter-class>com.weijia.filterservlet.LogFilter</filter-class>    
    </filter>    
    <filter-mapping>    
        <filter-name>logfilter</filter-name>    
        <url-pattern>/*</url-pattern>    
    </filter-mapping>  
      
<!-- 編碼過濾器 -->    
    <filter>    
        <filter-name>setCharacterEncoding</filter-name>    
        <filter-class>com.weijia.filterservlet.EncodingFilter</filter-class>    
        <init-param>    
            <param-name>encoding</param-name>    
            <param-value>utf-8</param-value>    
        </init-param>    
    </filter>    
    <filter-mapping>    
        <filter-name>setCharacterEncoding</filter-name>    
        <url-pattern>/*</url-pattern>    
    </filter-mapping>    

 

然後看一下編碼過濾器:

package com.weijia.filterservlet;  
  
import java.io.IOException;  
import java.util.Enumeration;  
import java.util.HashMap;  
  
import javax.servlet.Filter;  
import javax.servlet.FilterChain;  
import javax.servlet.FilterConfig;  
import javax.servlet.ServletException;  
import javax.servlet.ServletRequest;  
import javax.servlet.ServletResponse;  
  
public class EncodingFilter implements Filter {    
    private String encoding;    
    private HashMap<String,String> params = new HashMap<String,String>();    
    // 項目結束時就已經進行銷毀    
    public void destroy() {    
        System.out.println("end do the encoding filter!");    
        params=null;    
        encoding=null;    
    }    
    public void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException {    
        System.out.println("before encoding " + encoding + " filter!");    
        req.setCharacterEncoding(encoding);    
        chain.doFilter(req, resp);          
        System.out.println("after encoding " + encoding + " filter!");    
        System.err.println("----------------------------------------");    
    }    
     
    // 項目啟動時就已經進行讀取    
    public void init(FilterConfig config) throws ServletException {    
        System.out.println("begin do the encoding filter!");    
        encoding = config.getInitParameter("encoding");    
        for (Enumeration<?> e = config.getInitParameterNames(); e.hasMoreElements();) {    
            String name = (String) e.nextElement();    
            String value = config.getInitParameter(name);    
            params.put(name, value);    
        }    
    }    
 }    

 


日志過濾器:

package com.weijia.filterservlet;  
  
import java.io.IOException;  
  
import javax.servlet.Filter;  
import javax.servlet.FilterChain;  
import javax.servlet.FilterConfig;  
import javax.servlet.ServletException;  
import javax.servlet.ServletRequest;  
import javax.servlet.ServletResponse;  
import javax.servlet.http.HttpServletRequest;  
  
public class LogFilter implements Filter {    
      
    public FilterConfig config;    
     
    public void destroy() {    
        this.config = null;    
        System.out.println("end do the logging filter!");  
    }    
     
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {    
        System.out.println("before the log filter!");    
        // 將請求轉換成HttpServletRequest 請求    
        HttpServletRequest hreq = (HttpServletRequest) req;    
        // 記錄日志    
        System.out.println("Log Filter已經截獲到用戶的請求的地址:"+hreq.getServletPath() );    
        try {    
            // Filter 只是鏈式處理,請求依然轉發到目的地址。    
            chain.doFilter(req, res);    
        } catch (Exception e) {    
            e.printStackTrace();    
        }    
        System.out.println("after the log filter!");    
    }    
     
    public void init(FilterConfig config) throws ServletException {    
        System.out.println("begin do the log filter!");    
        this.config = config;    
    }    
     
 }    

 


測試Servlet:

package com.weijia.filterservlet;  
  
import java.io.IOException;  
  
import javax.servlet.ServletException;  
import javax.servlet.http.HttpServlet;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
  
public class FilterServlet extends HttpServlet {  
  
    private static final long serialVersionUID = 1L;  
  
    public void doGet(HttpServletRequest request, HttpServletResponse response)  
            throws ServletException, IOException {  
        response.setDateHeader("expires", -1);  
    }  
  
    public void doPost(HttpServletRequest request, HttpServletResponse response)  
            throws ServletException, IOException {  
    }  
  
}  

訪問FilterServlet

運行結果:

before the log filter!
Log Filter已經截獲到用戶的請求的地址:/FilterServlet
before encoding utf-8 filter!
after encoding utf-8 filter!
----------------------------------------
after the log filter!


我們從運行結果可以看到這個過濾器的調用關系:

類似於C++中的構造函數和析構函數的調用順序,

這裡我們在web.xml中注冊的是先注冊日志過濾器的,然後再注冊

 

當我們重新部署應用的時候發現:

會先銷毀上次的過濾器,然後再重新注冊一下

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved