Servlet之過濾器總結--Filter

            前言

                          咱們知道實際開發中咱們可能有這種須要:對於某個網站來講須要限制一些ip對該網站的訪html

                     問。例如教育網站,一般咱們只能訪問到它的首頁,至於教務管理的頁面,不在該教育網段範java

                     圍的IP是不能訪問到的。web

                          另外,在實際的項目中咱們可能涉及到字符的轉碼,若是在每一個頁面都去設置轉碼會十分的編程

                    麻煩,這時就可使用Filter來解決了。瀏覽器

             Filter

                            Servlet過濾器Fileter是一個小型的web組件,它們經過攔截請求和響應,以便查看、提取或服務器

                      以某種方式操做客戶端和服務器之間交換的數據,實現「過濾」的功能。Filter一般封裝了一些功app

                      能的web組件,過濾器提供了一種面向對象的模塊化機制,將任務封裝到一個可插入的組件中,jsp

                      Filter組件經過配置文件來聲明,並動態的代理。ide

                            簡單來講Servlet的Filter是:模塊化

                            ●  聲明式的:經過在web.xml配置文件中聲明,容許添加、刪除過濾器,而無需改動任何

                                 應用程序代碼或jsp頁面。

                           ●  靈活的:過濾器可用於客戶端的直接調用執行預處理和後期的處理工做,經過過濾鏈可

                                 以實現一些靈活的功能。

                           ●  可移植的:因爲現今各個web容器都是以Servlet的規範進行設計的,所以Servlet過濾器

                                 一樣是跨容器的。

                           ●  可重用的:基於其可移植性和聲明式的配置方式,Filter是可重用的。

                            總的來講,Servlet的過濾器是經過一個配置文件來靈活的聲明的模塊化可重用組件。

                       過濾器動態的截獲傳入的請求和傳出的響應,在不修改程序代碼的狀況下,透明的添加或刪除

                       他們。其獨立於任何平臺和web容器。

               Filter體系結構

                               如其名字所暗示的同樣,Servlet過濾器用於攔截傳入的請求和傳出的響應,並監視、修改

                         處理web工程中的數據流。過濾器是一個可插入的自由組件。

                               web資源能夠不配置過濾器、也能夠配置單個過濾器,也能夠配置多個過濾器,造成一個

                         過濾器鏈。Filter接受用戶的請求,並決定將請求轉發給鏈中的下一個組件,或者終止請求

                         直接向客戶端返回一個響應。若是請求被轉發了,它將被傳遞給鏈中的下一個過濾器(以

                         web.xml過濾器的配置順序爲標準)。這個請求在經過過濾鏈並被服務器處理以後,一個響應

                         將以相反的順序經過該鏈發送回去。這樣,請求和響應都獲得了處理。

                              Filter能夠應用在客戶端和Servlet之間、servlet和serlvet或jsp之間,以及jsp之間。而且

                         能夠經過配置信息,靈活的使用那個過濾器。

                Filter工做原理

                               基於Filter體系結構的描述,咱們能夠看出Filter的工做原理,簡單的經過一幅流程圖加以

                            演示:

                     

                              客戶端瀏覽器在訪問web服務器的某個具體資源的時候,通過過濾器1中code1代碼塊的相

                           關處理以後,將request請求傳遞給過濾鏈中的下一個過濾器2,(過濾鏈的順序以配置文件

                           中的順序爲基準)過濾器2處理完以後,request就傳遞的Servlet完成相應的邏輯。

                              返回響應的過程相似,只是過濾鏈的順序相反,這裏就很少說了。

                  Filter的建立過程

                                  在具體去實現FIlter以前,先去看看Filter的源碼,簡單的看看實現Filter須要作的事,從

                            源碼中能夠看出,要編寫一個過濾器必須實現Filter接口。實現其接口規定的方法。

                                   ★  實現javax.servlet.Filter接口

                                   ★ 實現init方法,讀取過濾器的初始化參數

                                   ★ 實現doFilter方法,完成對請求或響應的過濾

                                   ★ 調用FilterChain接口對象的doFilter方法,向後續的過濾器傳遞請求或響應

                                  一個簡單的字符編碼處理的過濾器實現:

package com.kiritor.filter;  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;  public class EncodeFilter implements Filter{     //定義替換後的字符集,從過濾器的配置參數中讀取     String newCharSet;     public void destroy(){     }     public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException      {         //處理請求字符集         request.setCharacterEncoding(newCharSet);                  //傳遞給下一個過濾器。這裏沒有下一個,做爲過濾器的規則和良好的編程習慣,應該加上         chain.doFilter(request,response);          //處理響應字符集         response.setContentType("text/html;charset="+newCharSet);     }          public void init(FilterConfig filterConfig)throws ServletException      {         //從過濾器的配置中得到初始化參數,若是沒有就使用默認值         if(filterConfig.getInitParameter("newcharset")!=null)         {             newCharSet = filterConfig.getInitParameter("newcharset");         }         else             newCharSet = "GB2312";     } }
                           這裏對於過濾器對請求和響應的具體"過濾"過程,筆者就很少提了。

                Filter的配置

                                Filter是一個可插入的web組件,必須在web.xml文件中配置纔有效,那麼Filter是如何

                           配置的呢?針對上述字符編碼的Filter,配置信息以下:                 

 <!-- 指定過濾器的名字,初始化參數等信息 -->   <filter>     <display-name>EncodeFilter</display-name>     <filter-name>EncodeFilter</filter-name>     <filter-class>com.kiritor.filter.EncodeFilter</filter-class>   </filter>   <!-- 指定過濾器的URL關聯/*表示全部的 -->   <filter-mapping>     <filter-name>EncodeFilter</filter-name>     <url-pattern>/*</url-pattern>   </filter-mapping>
                                 url-pattern配置詳解
                            在web.xml文件中,如下語法用於定義映射:

                               l 以」/’開頭和以」/*」結尾的是用來作路徑映射的。

                               l 之前綴」*.」開頭的是用來作擴展映射的。

                               l 「/」 是用來定義default servlet映射的。

                               l 剩下的都是用來定義詳細映射的。好比: /aa/bb/cc.action

                               因此,爲何定義」/*.action」這樣一個看起來很正常的匹配會錯?

                           由於這個匹配即屬於路徑映射,也屬於擴展映射,致使容器沒法判斷。

                Filter編程實例演示:

                               接下來筆者將演示一個IP過濾器,過濾掉某個具體的ip,並將客戶端的訪問記錄作

                           一個日誌文件記錄。實際的過程以下:

                               這裏筆者保留了字符處理的Filter,打印信息,以便更好的理解過濾鏈的執行狀況。

                               編寫IP過濾器:IPFilter

package com.kiritor.filter;  import java.io.IOException; import java.net.InetAddress;  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; import javax.servlet.http.HttpServletResponse;  import com.kiritor.logUtil.LogUtil;  /**  * Servlet Filter implementation class IPFilter  */ public class IPFilter implements Filter {      /**      * Default constructor.       */     private String ip;     private FilterConfig config;     public IPFilter() {         // TODO Auto-generated constructor stub     }      /**      * @see Filter#destroy()      */     public void destroy() {         // TODO Auto-generated method stub     }      /**      * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)      */     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {         HttpServletRequest req= (HttpServletRequest)request;         HttpServletResponse res = (HttpServletResponse)response;         // 獲取客戶請求lP         /*下面那條註釋語句獲得的是IPV6地址,          * 客戶端和服務器在同一臺機子上是得不到ipv4地址的**/         //String remoteIP = request.getRemoteAddr();         //以這種方式獲取IPv4地址         InetAddress inet = InetAddress.getLocalHost();         LogUtil.logRecord(inet.getHostAddress());         //System.out.println(remoteIP);         if (inet.getHostAddress().equals("192.168.0.3")){                          req.getRequestDispatcher("ipErr.jsp").forward(request, response);                      } else {             chain.doFilter(request, response);// 調用過濾鏈上的下一個過濾器         }         System.out.println("IPFilter處理");         chain.doFilter(request, response);     }      /**      * @see Filter#init(FilterConfig)      */     public void init(FilterConfig fConfig) throws ServletException {         //從過濾器的配置中得到初始化參數,若是沒有就使用默認值         this.config = fConfig;         if(fConfig.getInitParameter("ipinfo")!=null)         {             ip = fConfig.getInitParameter("ipinfo");         }         else             ip = "192.168.0.3";     }  }   
                        接下來進行配置:

        

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">   <display-name>Servlet_Filter</display-name>   <welcome-file-list>     <welcome-file>index.html</welcome-file>     <welcome-file>index.htm</welcome-file>     <welcome-file>index.jsp</welcome-file>     <welcome-file>default.html</welcome-file>     <welcome-file>default.htm</welcome-file>     <welcome-file>default.jsp</welcome-file>   </welcome-file-list>   <filter>     <display-name>EncodeFilter</display-name>     <filter-name>EncodeFilter</filter-name>     <filter-class>com.kiritor.filter.EncodeFilter</filter-class>     <init-param>         <param-name>newcharset</param-name>         <param-value>gb2312</param-value>     </init-param>   </filter>   <filter-mapping>     <filter-name>EncodeFilter</filter-name>     <url-pattern>/*</url-pattern>   </filter-mapping>   <filter>     <display-name>IPFilter</display-name>     <filter-name>IPFilter</filter-name>     <filter-class>com.kiritor.filter.IPFilter</filter-class>     <init-param>         <param-name>ipinfo</param-name>         <param-value>192.168.0.3</param-value>     </init-param>   </filter>   <filter-mapping>     <filter-name>IPFilter</filter-name>     <url-pattern>/*</url-pattern>   </filter-mapping> </web-app>
                               接下來簡單的日誌文件操做: 
package com.kiritor.logUtil;  import java.io.FileOutputStream; import java.text.SimpleDateFormat; import java.util.Date;  import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest;  /**  * @author Kiritor  * 2013-6-15 上午8:21:19  * 功能:實現IP訪問的日誌記錄  */ public  class LogUtil {    public static void logRecord(String ip)    {        try{            FileOutputStream out = new FileOutputStream("D:\\log.txt",true);                        Date date = new Date();            SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd a  hh:mm:ss");            String str = f.format(date);                        String runningMsg = str+"--->\r\n"+                  ip +"登陸"                     +"\r\n";            out.write(runningMsg.getBytes());            out.close();                    }catch(Exception e){            e.printStackTrace();        }    } } 
                           ok,咱們看看實際的運行效果吧!
         

                           日誌文檔信息記錄以下:        

2013-06-15 上午  08:56:59---> 192.168.0.3登陸 2013-06-15 上午  09:00:08---> 192.168.0.3登陸 
                              好了,對於Servlet過濾器的學習就到這個地方了,固然上述實例只是Filter的簡單運用

                      十分的靈活與方便。

                       參考文檔:

                        http://www.ibm.com/developerworks/cn/java/j-pj2ee10/index.html

                                                                                                                                     By      Kiritor

                                                                                                                                     2013 /06 /15

相關文章
相關標籤/搜索