Look into it ~

          present
          隨筆 - 32, 文章 - 0, 評論 - 3, 引用 - 0
          數據加載中……

          servlet過濾器

          servlet過濾器

          1. Servlet過濾器基礎
          Servlet過濾器是Servlet的一種特殊用法,主要用來完成一些通用的操作。比如編碼的過濾,判斷用戶的登陸狀態等等。Servlet過濾器的適用場合:
          A.認證過濾
          B.登錄和審核過濾
          C.圖像轉換過濾
          D.數據壓縮過濾
          E.加密過濾
          F.令牌過濾
          G.資源訪問觸發事件過濾
          Servlet過濾器接口的構成:
          所有的Servlet過濾器類都必須實現javax.servlet.Filter接口。這個接口含有3個過濾器類必須實現的方法:
          方法 說明
          init(FilterConfig cfg) 這是Servlet過濾器的初始化方法,性質等同與servlet的init方法。
          doFilter(ServletRequest,ServletResponse,FilterChain) 完成實際的過濾操作,當請求訪問過濾器關聯的URL時,Servlet容器將先調用過濾器的doFilter方法。FilterChain參數用于訪問后續過濾器
          destroy() Servlet容器在銷毀過濾器實例前調用該方法,這個方法中可以釋放Servlet過濾器占用的資源。性質等同與servlet的destory()方法。
          Servlet過濾器的創建步驟:
          A.實現javax.servlet.Filter接口的servlet類
          B.實現init方法,讀取過濾器的初始化函數
          C.實現doFilter方法,完成對請求或過濾的響應
          D.調用FilterChain接口對象的doFilter方法,向后續的過濾器傳遞請求或響應
          F.在web.xml中配置Filter
          2.使用過濾器處理中文問題
             當用用戶登陸頁面輸入帳號時,如果輸入是中文,后臺servlet再次輸出這個內容時,可能就會是亂碼,這是因為serlvet中默認是以ISO-8859-1格式編碼的,如果后臺有多個Servlet,多個參數,這樣就不合適,這個問題,我們可以通過一個過濾器統一解決,使后臺的輸出輸出都支持中文!將ISO-8859-1轉碼為GBK的那段代碼!
          3.使用過濾器認證用戶:
          每個過濾器也可以配置初始化參數,可以將不需要過濾的地址配置到這個Filter的配置參數中,過濾時,如果請求地址在配置參數中,則放行,這樣 就避免了在程序中硬編碼。每個Filter中初始化時,都可以得到配置對象,在Filter中配置二個不需要過濾的地址,一個是登陸頁面,一個是執行登陸 認證的servlet;
          4.Servlet監聽器
          類似與Swing界面應用開發,Servlet也可以創建監聽器,以對Servlet容器,或Servlet中以象的事件做出反應。Servlet監聽器主要有以下幾種:
          ServletRequestListener ,ServletRequestAttributeListener,
          HttpSessionActivationListener ,HttpSessionBindingListener ,
          HttpSessionAttributeListener,HttpSessionListener,
          ServletContextListener等等。
          這些監聽器主要用來監聽session,request,application這三個對象里存取數據的變化。
          ----------------------------------------------------------------------------------------------------------------

          servlet API中最重要的一個功能就是能夠為servlet和JSP頁面定義過濾器。過濾器提供了某些早期服務器所支持的非標準“servlet鏈接”的一種功能強大且標準的替代品。
                                                                                                          
               過濾器是一個程序,它先于與之相關的servlet或JSP頁面運行在服務器上。過濾器可附加到一個或多個servlet或JSP頁面上,并且可以檢查進入這些資源的請求信息。在這之后,過濾器可以作如下的選擇:

          1. 以常規的方式調用資源(即,調用servlet或JSP頁面)。

          2.利用修改過的請求信息調用資源。

          3. 調用資源,但在發送響應到客戶機前對其進行修改

          4. 阻止該資源調用,代之以轉到其他的資源,返回一個特定的狀態代碼或生成替換輸出。

          過濾器提供了幾個重要好處 :


                  首先,它以一種模塊化的或可重用的方式封裝公共的行為。你有30個不同的serlvet或JSP頁面,需要壓縮它們的內容以減少下載時間嗎?沒問題:構造一個壓縮過濾器,然后將它應用到30個資源上即可。

          其次,利用它能夠將高級訪問決策與表現代碼相分離。這對于JSP特別有價值,其中一般希望將幾乎整個頁面集中在表現上,而不是集中在業務邏輯上。例如,希 望阻塞來自某些站點的訪問而不用修改各頁面(這些頁面受到訪問限制)嗎?沒問題:建立一個訪問限制過濾器并把它應用到想要限制訪問的頁面上即可。

               最后,過濾器使你能夠對許多不同的資源進行批量性的更改。你有許多現存資源,這些資源除了公司名要更改外其他的保持不變,能辦到么?沒問題:構造一個串替換過濾器,只要合適就使用它。

               但要注意,過濾器只在與servlet規范2.3版兼容的服務器上有作用。如果你的Web應用需要支持舊版服務器,就不能使用過濾器。

          1.   建立基本過濾器

          建立一個過濾器涉及下列五個步驟:
          1)建立一個實現Filter接口的類。這個類需要三個方法,分別是:doFilter、init和destroy。
                 doFilter方法包含主要的過濾代碼(見第2步),init方法建立設置操作,而destroy方法進行清楚。

          2)在doFilter方法中放入過濾行為。doFilter方法的第一個參數為ServletRequest對象。此對象給過濾器提供了對進入的信息 (包括表單數據、cookie和HTTP請求頭)的完全訪問。第二個參數為ServletResponse,通常在簡單的過濾器中忽略此參數。最后一個參 數為FilterChain,如下一步所述,此參數用來調用servlet或JSP頁。

          3)調用FilterChain對象的doFilter方法。Filter接口的doFilter方法取一個FilterChain對象作為它的一個參 數。在調用此對象的doFilter方法時,激活下一個相關的過濾器。如果沒有另一個過濾器與servlet或JSP頁面關聯,則servlet或JSP 頁面被激活。

          4)對相應的servlet和JSP頁面注冊過濾器。在部署描述符文件(web.xml)中使用filter和filter-mapping元素。

          5)禁用激活器servlet。防止用戶利用缺省servlet URL繞過過濾器設置。

          1.1   建立一個實現Filter接口的類
                所有過濾器都必須實現javax.servlet.Filter。這個接口包含三個方法,分別為doFilter、init和destroy。

          public void doFilter(ServletRequset request,
                               ServletResponse response,
                               FilterChain chain)
               thows ServletException, IOException

          每當調用一個過濾器(即,每次請求與此過濾器相關的servlet或JSP頁面)時,就執行其doFilter方法。正是這個方法包含了大部分過濾邏輯。 第一個參數為與傳入請求有關的ServletRequest。對于簡單的過濾器,大多數過濾邏輯是基于這個對象的。如果處理HTTP請求,并且需要訪問諸 如getHeader或getCookies等在ServletRequest中無法得到的方法,就要把此對象構造成 HttpServletRequest。

          第二個參數為ServletResponse。除了在兩個情形下要使用它以外,通常忽略這個參數。首先,如果希望完全阻塞對相關servlet或JSP頁 面的訪問??烧{用response.getWriter并直接發送一個響應到客戶機。其次,如果希望修改相關的servlet或JSP頁面的輸出,可把響 應包含在一個收集所有發送到它的輸出的對象中。然后,在調用serlvet或JSP頁面后,過濾器可檢查輸出,如果合適就修改它,之后發送到客戶機。

          DoFilter的最后一個參數為FilterChain對象。對此對象調用doFilter以激活與servlet或JSP頁面相關的下一個過濾器。如果沒有另一個相關的過濾器,則對doFilter的調用激活servlet或JSP本身。

          public void init(FilterConfig config)   thows ServletException

          init方法只在此過濾器第一次初始化時執行,不是每次調用過濾器都執行它。對于簡單的過濾器,可提供此方法的一個空體,但有兩個原因需要使用init。 首先,FilterConfig對象提供對servlet環境及web.xml文件中指派的過濾器名的訪問。因此,普遍的辦法是利用init將 FilterConfig對象存放在一個字段中,以便doFilter方法能夠訪問servlet環境或過濾器名.其次,FilterConfig對象具 有一個getInitParameter方法,它能夠訪問部署描述符文件(web.xml)中分配的過濾器初始化參數。

          public void destroy( )
               大多數過濾器簡單地為此方法提供一個空體,不過,可利用它來完成諸如關閉過濾器使用的文件或數據庫連接池等清除任務。

          1.2   將過濾行為放入doFilter方法

               doFilter方法為大多數過濾器地關鍵部分。每當調用一個過濾器時,都要執行doFilter。對于大多數過濾器來說,doFilter執行的步驟是 基于傳入的信息的。因此,可能要利用作為doFilter的第一個參數提供的ServletRequest。這個對象常常構造為 HttpServletRequest類型,以提供對該類的更特殊方法的訪問。

          1.3   調用FilterChain對象的doFilter方法
               Filter接口的doFilter方法以一個FilterChain對象作為它的第三個參數。在調用該對象的doFilter方法時,激活下一個相關的 過濾器。這個過程一般持續到鏈中最后一個過濾器為止。在最后一個過濾器調用其FilterChain對象的doFilter方法時,激活servlet或 頁面自身。
          但是,鏈中的任意過濾器都可以通過不調用其FilterChain的doFilter方法中斷這個過程。在這樣的情況下,不再調用JSP頁面的serlvet,并且中斷此調用過程的過濾器負責將輸出提供給客戶機。

          1.4   對適當的servlet和JSP頁面注冊過濾器

               部署描述符文件的2.3版本引入了兩個用于過濾器的元素,分別是:filter和filter-mapping。filter元素向系統注冊一個過濾對象,filter-mapping元素指定該過濾對象所應用的URL。

          1.filter元素
          filter元素位于部署描述符文件(web.xml)的前部,所有filter-mapping、servlet或servlet-mapping元素之前。filter元素具有如下六個可能的子元素:

          1、 icon   這是一個可選的元素,它聲明IDE能夠使用的一個圖象文件。
          2、filter-name   這是一個必需的元素,它給過濾器分配一個選定的名字。
          3、display-name   這是一個可選的元素,它給出IDE使用的短名稱。
          4、 description   這也是一個可選的元素,它給出IDE的信息,提供文本文檔。
          5、 filter-class   這是一個必需的元素,它指定過濾器實現類的完全限定名。
          6、 init-param   這是一個可選的元素,它定義可利用FilterConfig的getInitParameter方法讀取的初始化參數。單個過濾器元素可包含多個init-param元素。

          請注意,過濾是在serlvet規范2.3版中初次引入的。因此,web.xml文件必須使用DTD的2.3版本。下面介紹一個簡單的例子:

            <xml version="1.0" encoding="ISO-8859-1"?>
              
          DOCTYPE web-app PUBLIC
                  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
                   "http://java.sun.com/dtd/web-app_2_3.dtd"
          >

              
          <web-app>
               
          <filter>
                  
          <filter-name>MyFilterfilter-name>
                  
          <filter-class>myPackage.FilterClassfilter-class>
                
          filter>
                

                
          <filter-mapping>...filter-mapping>
               <
          web-app>


          2.filter-mapping元素

              filter-mapping元素位于web.xml文件中filter元素之后serlvet元素之前。它包含如下三個可能的子元素:

          1、 filter-name   這個必需的元素必須與用filter元素聲明時給予過濾器的名稱相匹配。

          2、 url-pattern   此元素聲明一個以斜杠(/)開始的模式,它指定過濾器應用的URL。所有filter-mapping元素中必須提供url-pattern或 servlet-name。但不能對單個filter-mapping元素提供多個url-pattern元素項。如果希望過濾器適用于多個模式,可重復 整個filter-mapping元素。

          3、 servlet-name   此元素給出一個名稱,此名稱必須與利用servlet元素給予servlet或JSP頁面的名稱相匹配。不能給單個filter-mapping元素提供 多個servlet-name元素項。如果希望過濾器適合于多個servlet名,可重復這個filter-mapping元素。
          下面舉一個例子:

          xml version="1.0" encoding="ISO-8859-1"?>
              
          DOCTYPE web-app PUBLIC
                  
          "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"

                  
          "http://java.sun.com/dtd/web-app_2_3.dtd">
              
          <web-app>
                
          <filter>
                  
          <filter-name>MyFilterfilter-name>
                  
          <filter-class>myPackage.FilterClassfilter-class>
                
          filter>
                

                
          <filter-mapping>
                  
          <filter-name>MyFilterfilter-name>
                  
          <url-pattern>/someDirectory/SomePage.jspurl-pattern>
                
          filter-mapping>
              
          web-app>


          1.5   禁用激活器servlet
               在對資源應用過濾器時,可通過指定要應用過濾器的URL模式或servlet名來完成。如果提供servlet名,則此名稱必須與web.xml的 servlet元素中給出的名稱相匹配。如果使用應用到一個serlvet的URL模式,則此模式必須與利用web.xml的元素servlet- mapping指定的模式相匹配。但是,多數服務器使用“激活器servlet”為servlet體統一個缺省的URL:http: //host/WebAppPrefix/servlet/ServletName。需要保證用戶不利用這個URL訪問servlet(這樣會繞過過濾器 設置)。
          例如,假如利用filter和filter-mapping指示名為SomeFilter的過濾器應用到名為SomeServlet的servlet,則如下:

          <filter>
                
          <filter-name>SomeFilterfilter-name>
                
          <filter-class>somePackage.SomeFilterClassfilter-class>
             <
          filter>
              

              
          <filter-mapping>
                
          <filter-name>SomeFilterfilter-name>
                
          <servlet-name>SomeServletservlet-name>
               <
          filter-mapping>



          接著,用servlet和servlet-mapping規定URL   http://host/webAppPrefix/Blah 應該調用SomeSerlvet,如下所示:

          <filter>
                
          <filter-name>SomeFilterfilter-name>
                
          <filter-class>somePackage.SomeFilterClassfilter-class>
              
          filter>
              

              
          <filter-mapping>
                
          <filter-name>SomeFilterfilter-name>
                
          <servlet-name>/Blahservlet-name>
               <
          filter-mapping>



          現在,在客戶機使用URL   http://host/webAppPrefix/Blah 時就會調用過濾器。過濾器不應用到
          http://host/webAppPrefix/servlet/SomePackage.SomeServletClass。
          盡管有關閉激活器的服務器專用方法。但是,可移植最強的方法時重新映射Web應用鐘的/servlet模式,這樣使所有包含此模式的請求被送到相同的 servlet中。為了重新映射此模式,首先應該建立一個簡單的servlet,它打印一條錯誤消息,或重定向用戶到頂層頁。然后,使用servlet和 servlet-mapping元素發送包含/servlet模式的請求到該servlet。程序清單9-1給出了一個簡短的例子。

          程序清單9-1 web.xml(重定向缺省servlet URL的摘錄)

           xml version="1.0" encoding="ISO-8859-1"?>
              
          DOCTYPE web-app PUBLIC
                   "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
                   "http://java.sun.com/dtd/web-app_2_3.dtd"
          >

              
          <web-app>
              

              
          <servlet>
                
          <servlet-name>Errorservlet-name>
                
          <servlet-class>somePackage.ErrorServletservlet-class>
              
          servlet>
              

              
          <servlet-mapping>
                
          <servlet-name>Errorservlet-name>
                
          <url-pattern>/servlet/*url-pattern>
              
          servlet-mapping>
              

              <
          web-app>

          -------------------------------------------------------------------------------------------
          解決亂碼

          web.xml加配置

          <!--   過濾器 -->
           <filter>
            <filter-name>Filter</filter-name>
            <filter-class>
             com.util.EncodingFilter<!-- 過濾器類 -->
            </filter-class>
            <init-param>
             <param-name>Encoding</param-name>
             <param-value>gb2312</param-value>
            </init-param>
           </filter>
           <filter-mapping>
            <filter-name>Filter</filter-name>
            <url-pattern>/*</url-pattern>
           </filter-mapping>

          EncodingFilter.java

          package com.hibernate.util;

          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 EncodingFilter implements Filter {
           protected FilterConfig config;

           protected String Encoding = null;

           public void init(FilterConfig config) throws ServletException {

            this.config = config;
            this.Encoding = config.getInitParameter("Encoding");

           }

           public void doFilter(ServletRequest request, ServletResponse response,
             FilterChain chain) throws IOException, ServletException {

            if (request.getCharacterEncoding() == null) {
             if (Encoding != null) {
              request.setCharacterEncoding(Encoding);
              response.setCharacterEncoding(Encoding);
             }
            }
            chain.doFilter(request,response);
           }
           public void destroy() {}
          }

          OK!!!

          ----------------------------------------------------------------------------------------------------

          很簡單的過濾器,就是為了記錄一個url的請求時間 filter:
          1. package com.javaeye.wqf;  
          2. import javax.servlet.*;  
          3.   
          4. public class CounterFilter implements Filter {  
          5.     public void doFilter(ServletRequest request, ServletResponse response,  
          6.             FilterChain chain) throws IOException, ServletException {  
          7.         long start = System.currentTimeMillis();  
          8.         System.out.println("Filter start at "+start);  
          9.         chain.doFilter(request, response);  
          10.         long end = System.currentTimeMillis();  
          11.         System.out.println("Filter end at "+end);  
          12.     } 



          1. <filter>  
          2.     <filter-name>test</filter-name>  
          3.     <filter-class>com.javaeye.wqf.CounterFilter</filter-class>  
          4. </filter>  
          5.   
          6. <filter-mapping>  
          7.     <filter-name>test</filter-name>  
          8.     <url-pattern>/*</url-pattern>  
          9. </filter-mapping> 
          一般情況下是沒什么問題,但是當我下載一個稍微大的文件時,跳出確認窗口,如果選擇的是cancel,
          就會發現filter并沒有返回,也就是說
          1. System.out.println("Filter end at "+end); 
          并沒有執行. 原因是:

          chain.doFilter(request, response);  
          執行到這里時會從這里調用剩下的filter和servlet,所以這個調用將會是一個很長的過程。
          在這個調用里,將會完全通過request和resonse去操作連接,取得/發送數據,如果連接出現異常,將直接彈出Exception
          你的代碼里沒有捕獲異常,所以如果出現異常,chain.doFilter后面的就不會執行。
          可以把chain.doFilter放到try finally結構中,保證后續會被執行




          posted on 2008-10-28 14:58 LukeW 閱讀(349) 評論(0)  編輯  收藏 所屬分類: J2EE & DB


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 剑河县| 兴业县| 青神县| 元氏县| 酉阳| 江西省| 卓资县| 石首市| 巩留县| 六安市| 龙陵县| 霸州市| 徐州市| 襄城县| 崇义县| 古丈县| 广宁县| 神农架林区| 行唐县| 柯坪县| 海兴县| 林周县| 仁寿县| 桓台县| 宣汉县| 郴州市| 柘荣县| 富平县| 康定县| 化德县| 黑水县| 长春市| 邛崃市| 汾阳市| 沈丘县| 白水县| 墨江| 保德县| 黄浦区| 清涧县| 沾益县|