• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Khan's Notebook GCC/GNU/Linux Delphi/Window Java/Anywhere

            路漫漫,長修遠(yuǎn),我們不能沒有錢
            隨筆 - 173, 文章 - 0, 評論 - 257, 引用 - 0
            數(shù)據(jù)加載中……

            servlet和JSP過濾器Filter

            servlet API的2.3版本中最重要的一個新功能就是能夠為servlet和JSP頁面定義過濾器。過濾器提供了某些早期服務(wù)器所支持的非標(biāo)準(zhǔn)“servlet鏈接”的一種功能強大且標(biāo)準(zhǔn)的替代品。
            過濾器是一個程序,它先于與之相關(guān)的servlet或JSP頁面運行在服務(wù)器上。過濾器可附加到一個或多個servlet或JSP頁面上,并且可以檢查進(jìn)入這些資源的請求信息。在這之后,過濾器可以作如下的選擇:
            l 以常規(guī)的方式調(diào)用資源(即,調(diào)用servlet或JSP頁面)。
            l 利用修改過的請求信息調(diào)用資源。
            l 調(diào)用資源,但在發(fā)送響應(yīng)到客戶機前對其進(jìn)行修改
            l 阻止該資源調(diào)用,代之以轉(zhuǎn)到其他的資源,返回一個特定的狀態(tài)代碼或生成替換輸出。
            過濾器提供了幾個重要好處。
            首先,它以一種模塊化的或可重用的方式封裝公共的行為。你有30個不同的serlvet或JSP頁面,需要壓縮它們的內(nèi)容以減少下載時間嗎?沒問題:構(gòu)造一個壓縮過濾器(參閱第11節(jié)),然后將它應(yīng)用到30個資源上即可。
            其 次,利用它能夠?qū)⒏呒壴L問決策與表現(xiàn)代碼相分離。這對于JSP特別有價值,其中一般希望將幾乎整個頁面集中在表現(xiàn)上,而不是集中在業(yè)務(wù)邏輯上。例如,希望 阻塞來自某些站點的訪問而不用修改各頁面(這些頁面受到訪問限制)嗎?沒問題:建立一個訪問限制過濾器(參閱第8節(jié))并把它應(yīng)用到想要限制訪問的頁面上即 可。
            最后,過濾器使你能夠?qū)υS多不同的資源進(jìn)行批量性的更改。你有許多現(xiàn)存資源,這些資源除了公司名要更改外其他的保持不變,能辦到么?沒問題:構(gòu)造一個串替換過濾器(參閱第10節(jié)),只要合適就使用它。
            但要注意,過濾器只在與servlet規(guī)范2.3版兼容的服務(wù)器上有作用。如果你的Web應(yīng)用需要支持舊版服務(wù)器,就不能使用過濾器。
            1.  建立基本過濾器
            建立一個過濾器涉及下列五個步驟:
            1)建立一個實現(xiàn)Filter接口的類。這個類需要三個方法,分別是:doFilter、init和destroy。doFilter方法包含主要的過濾代碼(見第2步),init方法建立設(shè)置操作,而destroy方法進(jìn)行清楚。
            2) 在doFilter方法中放入過濾行為。doFilter方法的第一個參數(shù)為ServletRequest對象。此對象給過濾器提供了對進(jìn)入的信息(包括 表單數(shù)據(jù)、cookie和HTTP請求頭)的完全訪問。第二個參數(shù)為ServletResponse,通常在簡單的過濾器中忽略此參數(shù)。最后一個參數(shù)為 FilterChain,如下一步所述,此參數(shù)用來調(diào)用servlet或JSP頁。
            3)調(diào)用FilterChain對象的doFilter方法。 Filter接口的doFilter方法取一個FilterChain對象作為它的一個參數(shù)。在調(diào)用此對象的doFilter方法時,激活下一個相關(guān)的過 濾器。如果沒有另一個過濾器與servlet或JSP頁面關(guān)聯(lián),則servlet或JSP頁面被激活。
            4)對相應(yīng)的servlet和JSP頁面注冊過濾器。在部署描述符文件(web.xml)中使用filter和filter-mapping元素。
            5)禁用激活器servlet。防止用戶利用缺省servlet URL繞過過濾器設(shè)置。
            1.1  建立一個實現(xiàn)Filter接口的類
            所有過濾器都必須實現(xiàn)javax.servlet.Filter。這個接口包含三個方法,分別為doFilter、init和destroy。
            l public void doFilter(ServletRequset request, 
                                ServletResponse response,
                                FilterChain chain)
                thows ServletException, IOException
            每當(dāng)調(diào)用一個過濾器(即,每次請求與此過濾器相關(guān)的servlet或JSP頁面)時,就執(zhí)行其doFilter方法。正是這個方法包含了大部分過濾邏輯。
            第 一個參數(shù)為與傳入請求有關(guān)的ServletRequest。對于簡單的過濾器,大多數(shù)過濾邏輯是基于這個對象的。如果處理HTTP請求,并且需要訪問諸如 getHeader或getCookies等在ServletRequest中無法得到的方法,就要把此對象構(gòu)造成 HttpServletRequest。
            第二個參數(shù)為ServletResponse。除了在兩個情形下要使用它以外,通常忽略這個參數(shù)。首先, 如果希望完全阻塞對相關(guān)servlet或JSP頁面的訪問。可調(diào)用response.getWriter并直接發(fā)送一個響應(yīng)到客戶機。第7節(jié)給出詳細(xì)內(nèi) 容,第8節(jié)給出一個例子。其次,如果希望修改相關(guān)的servlet或JSP頁面的輸出,可把響應(yīng)包含在一個收集所有發(fā)送到它的輸出的對象中。然后,在調(diào)用 serlvet或JSP頁面后,過濾器可檢查輸出,如果合適就修改它,之后發(fā)送到客戶機。詳情請參閱第9節(jié)。
            DoFilter的最后一個參數(shù)為FilterChain對象。對此對象調(diào)用doFilter以激活與servlet或JSP頁面相關(guān)的下一個過濾器。如果沒有另一個相關(guān)的過濾器,則對doFilter的調(diào)用激活servlet或JSP本身。
            l public void init(FilterConfig config)
                thows ServletException
            init 方法只在此過濾器第一次初始化時執(zhí)行,不是每次調(diào)用過濾器都執(zhí)行它。對于簡單的過濾器,可提供此方法的一個空體,但有兩個原因需要使用init。首先, FilterConfig對象提供對servlet環(huán)境及web.xml文件中指派的過濾器名的訪問。因此,普遍的辦法是利用init將 FilterConfig對象存放在一個字段中,以便doFilter方法能夠訪問servlet環(huán)境或過濾器名。這種處理在第3節(jié)描述。其次, FilterConfig對象具有一個getInitParameter方法,它能夠訪問部署描述符文件(web.xml)中分配的過濾器初始化參數(shù)。初 始化參數(shù)的使用在第5節(jié)中描述。
            l public void destroy( )
            此方法在利用一個給定的過濾器對象永久地終止服務(wù)器(如關(guān)閉服務(wù)器)時調(diào)用。大多數(shù)過濾器簡單地為此方法提供一個空體,不過,可利用它來完成諸如關(guān)閉過濾器使用的文件或數(shù)據(jù)庫連接池等清除任務(wù)。
            1.2  將過濾行為放入doFilter方法
            doFilter 方法為大多數(shù)過濾器地關(guān)鍵部分。每當(dāng)調(diào)用一個過濾器時,都要執(zhí)行doFilter。對于大多數(shù)過濾器來說,doFilter執(zhí)行的步驟是基于傳入的信息 的。因此,可能要利用作為doFilter的第一個參數(shù)提供的ServletRequest。這個對象常常構(gòu)造為HttpServletRequest類 型,以提供對該類的更特殊方法的訪問。
            1.3  調(diào)用FilterChain對象的doFilter方法
            Filter接口的 doFilter方法以一個FilterChain對象作為它的第三個參數(shù)。在調(diào)用該對象的doFilter方法時,激活下一個相關(guān)的過濾器。這個過程一 般持續(xù)到鏈中最后一個過濾器為止。在最后一個過濾器調(diào)用其FilterChain對象的doFilter方法時,激活servlet或頁面自身。
            但是,鏈中的任意過濾器都可以通過不調(diào)用其FilterChain的doFilter方法中斷這個過程。在這樣的情況下,不再調(diào)用JSP頁面的serlvet,并且中斷此調(diào)用過程的過濾器負(fù)責(zé)將輸出提供給客戶機。詳情請參閱第7節(jié)。
            1.4  對適當(dāng)?shù)膕ervlet和JSP頁面注冊過濾器
            部署描述符文件的2.3版本引入了兩個用于過濾器的元素,分別是:filter和filter-mapping。filter元素向系統(tǒng)注冊一個過濾對象,filter-mapping元素指定該過濾對象所應(yīng)用的URL。
            1.filter元素
            filter元素位于部署描述符文件(web.xml)的前部,所有filter-mapping、servlet或servlet-mapping元素之前。filter元素具有如下六個可能的子元素:
            l icon  這是一個可選的元素,它聲明IDE能夠使用的一個圖象文件。
            l filter-name  這是一個必需的元素,它給過濾器分配一個選定的名字。
            l display-name  這是一個可選的元素,它給出IDE使用的短名稱。
            l description  這也是一個可選的元素,它給出IDE的信息,提供文本文檔。
            l filter-class  這是一個必需的元素,它指定過濾器實現(xiàn)類的完全限定名。
            l init-param  這是一個可選的元素,它定義可利用FilterConfig的getInitParameter方法讀取的初始化參數(shù)。單個過濾器元素可包含多個init-param元素。
            請注意,過濾是在serlvet規(guī)范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元素之前。它包含如下三個可能的子元素::
            l filter-name  這個必需的元素必須與用filter元素聲明時給予過濾器的名稱相匹配。
            l url-pattern  此元素聲明一個以斜杠(/)開始的模式,它指定過濾器應(yīng)用的URL。所有filter-mapping元素中必須提供url- pattern或servlet-name。但不能對單個filter-mapping元素提供多個url-pattern元素項。如果希望過濾器適用于 多個模式,可重復(fù)整個filter-mapping元素。
            l servlet-name  此元素給出一個名稱,此名稱必須與利用servlet元素給予servlet或JSP頁面的名稱相匹配。不能給單個 filter-mapping元素提供多個servlet-name元素項。如果希望過濾器適合于多個servlet名,可重復(fù)這個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
            在 對資源應(yīng)用過濾器時,可通過指定要應(yīng)用過濾器的URL模式或servlet名來完成。如果提供servlet名,則此名稱必須與web.xml的 servlet元素中給出的名稱相匹配。如果使用應(yīng)用到一個serlvet的URL模式,則此模式必須與利用web.xml的元素servlet- mapping指定的模式相匹配。但是,多數(shù)服務(wù)器使用“激活器servlet”為servlet體統(tǒng)一個缺省的URL:http: //host/WebAppPrefix/servlet/ServletName。需要保證用戶不利用這個URL訪問servlet(這樣會繞過過濾器 設(shè)置)。
            例如,假如利用filter和filter-mapping指示名為SomeFilter的過濾器應(yīng)用到名為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規(guī)定URL  http://host/webAppPrefix/Blah 應(yīng)該調(diào)用SomeSerlvet,如下所示:

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

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


            現(xiàn)在,在客戶機使用URL  http://host/webAppPrefix/Blah 時就會調(diào)用過濾器。過濾器不應(yīng)用到
            http://host/webAppPrefix/servlet/SomePackage.SomeServletClass。
            盡 管有關(guān)閉激活器的服務(wù)器專用方法。但是,可移植最強的方法時重新映射Web應(yīng)用鐘的/servlet模式,這樣使所有包含此模式的請求被送到相同的 servlet中。為了重新映射此模式,首先應(yīng)該建立一個簡單的servlet,它打印一條錯誤消息,或重定向用戶到頂層頁。然后,使用servlet和 servlet-mapping元素發(fā)送包含/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>


            2.  樣例:報告過濾器
            趁熱打鐵,我們來試驗一個簡單的過濾器,只要調(diào)用相關(guān)的servlet或JSP頁面,它就打印一條消息到標(biāo)準(zhǔn)輸出。為了完成此任務(wù),相應(yīng)的過濾器必須具有下面的內(nèi)容:
            1)實現(xiàn)Filter接口的一個類。這個類名為ReportFilter,如程序清單9-2所示。這個類對init和destroy方法提供空體。
            2) 在doFilter方法中過濾行為。每當(dāng)調(diào)用與這個過濾器相關(guān)的servlet或JSP頁面時,doFilter方法就生成一個打印輸出,此輸出列出請求 主機和調(diào)用的URL。因為getRequestURL方法位于HttpServletRequest而不是ServletRequest中,所以把 ServletRequest對象構(gòu)造為HttpServletRequest類型。
            3)調(diào)用FilterChain的doFilter方法。在打印輸出報告后,過濾器調(diào)用FilterChain的doFilter方法激活servlet或JSP頁面(如果有的話,調(diào)用下一個過濾器)
            4) 對Web應(yīng)用主頁和顯示TodaysSpecialservlet進(jìn)行注冊。首先,filter元素將名稱Reporter與類 moreservlets.filters.ReportFilter相關(guān)聯(lián)。然后,filter-mapping元素使用/index.jsp的url -pattern將過濾器與主頁相關(guān)聯(lián)。最后,filter-mapping元素使用TodaysSpecial的servlet-name將過濾器與 TodaysSpecialservlet(名稱TodaysSpecial是在servlet元素中聲明的)相關(guān)聯(lián)。參見程序清單9-3。
            5) 禁用激活器servlet。首先,建立一個RedirectorServlet(見程序清單9-6),它把接收到的所有請求重定向到此Web應(yīng)用的主頁。 接著,利用servlet和servlet-mapping元素(參見程序清單9-3)指定所有以http: //host/webAppPrefix/servlet/ 開始的URL都應(yīng)該激活RedirectorServlet。
            給出這些設(shè)置后,每當(dāng)客戶機請求此Web應(yīng)用主頁(程序清單9-4)或TodaysSpecialservlet(程序清單9-5)時,都調(diào)用此過濾器。

            程序清單9-2 ReportFilter.java

             
            package moreservlets.filters;

            import java.io.
            *;
            import javax.servlet.
            *;
            import javax.servlet.http.
            *;
            import java.util.
            *// For Date class

            /** Simple filter that prints a report on the standard output
            * each time an associated servlet or JSP page is accessed.
            */

            public class ReportFilter implements Filter {
              public 
            void doFilter(ServletRequest request,
                              ServletResponse response,
                              FilterChain chain)
                  throws ServletException, IOException {
                HttpServletRequest req 
            = (HttpServletRequest)request;
                System.out.println(req.getRemoteHost() 
            +
                               
            " tried to access " +
                               req.getRequestURL() 
            +
                               
            " on " + new Date() + ".");
                chain.doFilter(request,response);
              }

              public 
            void init(FilterConfig config)
                  throws ServletException {
              }

              public 
            void destroy() {}
            }


            程序清單9-3 web.xml(針對報告過濾器的摘錄)

            <?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>
                  <!-- Register the name "Reporter" for ReportFilter. -->
                  <filter>
                    <filter-name>Reporter</filter-name>
                    <filter-class>
                      moreservlets.filters.ReportFilter
                    </filter-class>
                  </filter>
                  <!-- ... -->
                  <!-- Apply the Reporter filter to home page. -->
                  <filter-mapping>
                    <filter-name>Reporter</filter-name>
                    <url-pattern>/index.jsp</url-pattern>
                  </filter-mapping>
                  <!-- Also apply the Reporter filter to the servlet named
                      "TodaysSpecial".
                  -->
                  <filter-mapping>
                    <filter-name>Reporter</filter-name>
                    <servlet-name>TodaysSpecial</servlet-name>
                  </filter-mapping>
                  <!-- ... -->
                
                  <!-- Give a name to the Today's Special servlet so that filters
                      can be applied to it.
                  -->
                  <servlet>
                    <servlet-name>TodaysSpecial</servlet-name>
                    <servlet-class>
                      moreservlets.TodaysSpecialServlet
                    </servlet-class>
                  </servlet>
                  <!-- ... -->
                
                  <!-- Make /TodaysSpecial invoke the servlet
                      named TodaysSpecial (i.e., moreservlets.TodaysSpecial).
                  -->
                  <servlet-mapping>
                    <servlet-name>TodaysSpecial</servlet-name>
                    <url-pattern>/TodaysSpecial</url-pattern>
                  </servlet-mapping>
                
                  <!-- Turn off invoker. Send requests to index.jsp. -->
                  <servlet-mapping>
                    <servlet-name>Redirector</servlet-name>
                    <url-pattern>/servlet/*</url-pattern>
                  </servlet-mapping>
                  <!-- ... -->
                </web-app>

             

            程序清單9-4 index.jsp
            <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
            <HTML>
            <HEAD>
            <TITLE>Filters 'R' Us</TITLE>
            <LINK REL=STYLESHEET
                    HREF="filter-styles.css"
                    TYPE="text/css">
            </HEAD>
            <BODY>
            <CENTER>
            <TABLE BORDER=5>
              <TR><TH CLASS="TITLE">Filters 'R' Us</TABLE>
            <P>
            <TABLE>
              <TR>
                <TH><IMG SRC="images/air-filter.jpg" ALT="Air Filter">
                <TH><IMG SRC="images/coffee-filter.gif" ALT="Coffee Filter">
                <TH><IMG SRC="images/pump-filter.jpg" ALT="Pump Filter">
              </TR>
            </TABLE>

            <H3>We specialize in the following:</H3>
            <UL>
              <LI>Air filters
              <LI>Coffee filters
              <LI>Pump filters
              <LI>Camera lens filters
              <LI>Image filters for Adobe Photoshop
              <LI>Web content filters
              <LI>Kalman filters
              <LI>Servlet and JSP filters
            </UL>
            Check out <A HREF="TodaysSpecial">Today's Special</A>.
            </CENTER>
            </BODY>
            </HTML>


            程序清單9-5 TodaysSpecialServlet.java
            package moreservlets;

            import java.io.*;
            import javax.servlet.*;
            import javax.servlet.http.*;

            /** Sample servlet used to test the simple filters. */

            public class TodaysSpecialServlet extends HttpServlet {
              private String title, picture;

              public void doGet(HttpServletRequest request,
                                HttpServletResponse response)
                    throws ServletException, IOException {
                updateSpecials();
                response.setContentType("text/html");
                PrintWriter out = response.getWriter();
                String docType =
                    "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 " +
                    "Transitional//EN\">\n";
                    out.println
                    (docType +
                    "<HTML>\n" +
                    "<HEAD><TITLE>Today's Special</TITLE></HEAD>\n" +
                    "<BODY BGCOLOR=\"WHITE\">\n" +
                    "<CENTER>\n" +
                    "<H1>Today's Special: " + title + "s!</H1>\n" +
                    "<IMG SRC=\"images/" + picture + "\"\n" +
                    " ALT=\"" + title + "\">\n" +
                    "<BR CLEAR=\"ALL\">\n" +
                    "Special deal: for only twice the price, you can\n" +
                    "<I>buy one, get one free!</I>.\n" +
                    "</BODY></HTML>");
              }

              // Rotate among the three available filter images.

              private void updateSpecials() {
                double num = Math.random();
                if (num < 0.333) {
                  title = "Air Filter";
                  picture = "air-filter.jpg";
                } else if (num < 0.666) {
                  title = "Coffee Filter";
                  picture = "coffee-filter.gif";
                } else {
                  title = "Pump Filter";
                  picture = "pump-filter.jpg";
                }
              }
            }


            程序清單9-6 RedirectorServlet.java
            package moreservlets;

            import java.io.*;
            import javax.servlet.*;
            import javax.servlet.http.*;

            /** Servlet that simply redirects users to the
            * Web application home page. Registered with the
            * default servlet URL to prevent clients from
            * using http://host/webAppPrefix/servlet/ServletName
            * to bypass filters or security settings that
            * are associated with custom URLs.
            */

            public class RedirectorServlet extends HttpServlet {
              public void doGet(HttpServletRequest request,
                                HttpServletResponse response)
                    throws ServletException, IOException {
                response.sendRedirect(request.getContextPath());
              }

              public void doPost(HttpServletRequest request,
                               HttpServletResponse response)
                    throws ServletException, IOException {
                doGet(request, response);
              }
            }


            3.  從過濾器中訪問servlet環(huán)境
            前 一節(jié)的ReportFilter只要調(diào)用指定的servlet或JSP頁面,就在標(biāo)準(zhǔn)輸出上打印一個報告。當(dāng)你在自己的桌面系統(tǒng)上運行一個服務(wù)器時,一般 會用一個顯示標(biāo)準(zhǔn)輸出的窗口,在開發(fā)過程中,標(biāo)準(zhǔn)輸出上的報告很好用。但在部署過程中,不可能訪問這個窗口。因此,一種自然的改進(jìn)是將報告寫入 servlet日志文件寫到標(biāo)準(zhǔn)輸出。
            Servlet API提供了兩個log方法:一個取一個簡單的String而另一個取一個String和 一個Throwable。這兩個方法都可以從GenericServlet或ServletContext類中使用。關(guān)于這兩個方法所用的日志文件的準(zhǔn)確 位置,請查看相關(guān)服務(wù)器的幫助文檔。問題是doFilter方法在與其相關(guān)的serlvet或JSP頁面之前執(zhí)行。因此,你不能訪問該servlet的實 例,從而不能調(diào)用從GenericServlet繼承的log方法。此外,API沒有體統(tǒng)從doFilter方法中訪問ServletContext的簡 單方法。可以訪問ServletContext的方法并且與過濾器相關(guān)的唯一類是FilterConfig,訪問ServletContext的方法為 getServletContext。FilterConfig對象被傳輸給init方法,但不會自動存放到doFilter可使用的某個位置。
            因 此,你必須自己存放FilterConfig。可建立一個FilterConfig類型的字段,然后重載init,將它的參數(shù)分配給該字段。因為一般只使 用FilterConfig對象來訪問ServletContext和過濾器名,所以可以存放該ServletContext和名稱在字段中。相面舉一個 例子:
                public class SomeFilter implements Filter {
                  protected FilterConfig config;
                  private ServletContext context;
                  private String filterName;
                  public void init(FilterConfig config)
                        throws ServletException {
                    this.config = config; // In case it is needed by subclass.
                    context = config.getServletContext();
                    filterName = config.getFilterName();
                  }

                // doFilter and destroy methods...
                }
            4.  例子:日志記錄過濾器
            我們來更新ReportFilter(程序清單9-2),以便消息進(jìn)入日志文件而不是標(biāo)準(zhǔn)輸出。為了完成這個任務(wù),過濾器應(yīng)該具有下列內(nèi)容:
            1)實現(xiàn)Filter接口的一個類。這個類名為LogFilter,如程序清單9-7所示。這個類的init方法在過濾器的字段中存放FilterConfig、ServletContext和過濾器名。它對destory方法提供一個空體。
            2)在doFilter方法中過濾行為。這個行為和ReportFilter的行為之間有兩點不同:報告放于日志文件中而不是標(biāo)準(zhǔn)輸出中,報告包括過濾器的名稱。
            3)調(diào)用FilterChain的doFilter方法。在打印出報告后,此過濾器調(diào)用FilterChain的doFilter方法激活鏈中的下一個過濾器(如果沒有更多的過濾器,則激活servlet或JSP頁面)。
            4) 對所有URL進(jìn)行注冊。首先,filter元素將名稱LogFilter與類moreservlets.filters.LogFilter相關(guān)聯(lián)。接 著,filter-mapping元素使用值為/*的url-pattern將此過濾器與Web應(yīng)用中所有URL相關(guān)聯(lián)。參看程序清單9-8。
            5)禁用激活servlet。這個操作已經(jīng)在第2節(jié)介紹過,這里就不再重復(fù)了。
            當(dāng) 這個Web應(yīng)用部署在一個外部服務(wù)器上且附加了日志記錄過濾器后,客戶機對此Web應(yīng)用主頁的請求將在日志文件中產(chǎn)生一個項,如: “audits.irs.gov tired to acces http://www.filtersrus.com/filters/index.jsp on Fri Oct 26 15: 16:15 EDT 2001.(Reported by Logger.)”。

            程序清單9-7 LogFilter.java
            package moreservlets.filters;

            import java.io.*;
            import javax.servlet.*;
            import javax.servlet.http.*;
            import java.util.*; // For Date class

            /** Simple filter that prints a report in the log file
            * whenever the associated servlets or JSP pages
            * are accessed.
            */

            public class LogFilter implements Filter {
              protected FilterConfig config;
              private ServletContext context;
              private String filterName;
              public void doFilter(ServletRequest request,
                                   ServletResponse response,
                                   FilterChain chain)
                    throws ServletException, IOException {
                HttpServletRequest req = (HttpServletRequest)request;
                context.log(req.getRemoteHost() +
                            " tried to access " +
                            req.getRequestURL() +
                            " on " + new Date() + ". " +
                            "(Reported by " + filterName + ".)");
                chain.doFilter(request,response);
              }

              public void init(FilterConfig config)
                    throws ServletException {
                this.config = config; // In case it is needed by subclass.
                context = config.getServletContext();
                filterName = config.getFilterName();
              }

              public void destroy() {}

            }


            程序清單9-8 web.xml(針對日志記錄過濾器的摘錄)
            <?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>
              <!-- ... -->

              <!-- Register the name "Logger" for LogFilter. -->
              <filter>
                <filter-name>Logger</filter-name>
                <filter-class>
                  moreservlets.filters.LogFilter
                </filter-class>
              </filter>
              <!-- ... -->

              <!-- Apply the Logger filter to all servlets and
              JSP pages.
              -->
              <filter-mapping>
                <filter-name>Logger</filter-name>
                <url-pattern>/*</url-pattern>
              </filter-mapping>

              <!-- ... -->
            </web-app>


            5.  利用過濾器的初始化參數(shù)
            對于servlet和JSP頁面,可通過提供初始化參數(shù)定制初始化行為。這個功能之所以游泳的原因在于有三組不同的人員可能希望定制servlet或JSP頁面的行為,這三組人員分別為:
            1)開發(fā)人員——他們通過更改serlvet或JSP頁面的代碼定制相應(yīng)的行為。
            2)最終用戶——他們通過在HTML表單中輸入值來定制相應(yīng)的行為。
            3) 部署人員——這是提供初始化參數(shù)服務(wù)的一組人員。這組人員是那些獲得現(xiàn)存Web應(yīng)用(或個別的servlet或JSP頁面)并在一個定制環(huán)境環(huán)境中部署它 們的人員。他們不一定是開發(fā)人員,因此期望他們修改servlet和JSP代碼是不現(xiàn)實的。但由于過濾器在它們所附加的servlet或JSP頁面之前執(zhí) 行,最終用戶一般不能定制過濾器的行為,這種能力仍然很有用。定制過濾器的行為用如下步驟完成:
            1)定義初始化參數(shù)。使用web.xml中的filter的init-param子元素以及param-nam和param-value子元素,如下所示。

                <filter>
                  <filter-name>SomeFilter</filter-name>
                  <filter-class>somePackage.SomeFilterClass</filter-class>
                  <init-param>
                    <param-name>param1</param-name>
                    <param-value>value1</param-value>
                  </init-param>
                  <init-param>
                    <param-name>param2</param-name>
                    <param-value>value2</param-value>
                  </init-param>
                </filter>

            2)讀初始化參數(shù)。從過濾器的inti方法中調(diào)用FilterConfig的getInitParameter方法。如下所示。

                public void init(FilterConfig config)
                    throws ServletException {
                  String val1 = config.getInitParameter("param1");
                  String val2 = config.getInitParameter("param2");
                  ...
                }

            3) 分析初始化參數(shù)。就像servlet和JSP的初始化參數(shù)一樣,每個過濾器的初始化都是String類型的。因此,如果想要其他類型的值,必須對它進(jìn)行轉(zhuǎn) 換。例如,可用Integer.parseInt將String“7”轉(zhuǎn)換為int 7。在分析時,別忘了檢查缺少的和不良的數(shù)據(jù)。缺少初始化參數(shù)將導(dǎo)致 從getInitParameter返回null。即使這些參數(shù)存在,也一個來考慮到部署人員不正確地對其值進(jìn)行格式化的可能性。例如,在轉(zhuǎn)換 String類型的值為int類型的值時,應(yīng)該將Integer.parseInt調(diào)用封在try/catch中,這個塊捕捉 NumberFormatException。這種辦法徹底地處理了null和格式化不正確的值。
            6.  例子:訪問時的過濾器
            第4節(jié)的 LogFilter,每當(dāng)相關(guān)的servlet或JSP頁面被訪問時,就在日志文件中打印一個項。假如想修改它,使它只注意不尋常時刻出現(xiàn)的訪問。因為 “不尋常”要視具體情況而定,servlet應(yīng)該提供不尋常時間范圍的缺省值,并允許部署人員通過初始化參數(shù)來重載這些值。為了完成這種功能,相應(yīng)的過濾 器應(yīng)該具有下面的內(nèi)容:
            1)實現(xiàn)Filter接口的一個類。這個類名為LateAccessFilter,如程序清單9-9所示。這個類的 init方法讀取startTime和endTime初始化參數(shù)。它嘗試作為init分析這些值,如果這些參數(shù)為null或未格式化為整數(shù),這使用缺省 值。然后,它將開始和結(jié)束事件、FilterConfig、ServletContext以及過濾器名存入過濾器的字段。最后, LateAccessFilter對destroy方法提供一個空體。
            2)在doFilter方法中過濾行為。這個方法查找當(dāng)前事件,看它問是否在開始時間和結(jié)束事件給出的范圍內(nèi),如果是,打印一個日志項。
            3)調(diào)用FilterChain的doFilter方法。在打印出報告后,此過濾器調(diào)用FilterChain的doFilter方法激活鏈中的下一個過濾器(如果沒有更多的過濾器,則激活servlet或JSP頁面)。
            4) 對Web應(yīng)用主頁進(jìn)行注冊;定義初始化參數(shù)。首先,filter元素將名稱LateAccessFilter與類 moreservlets.filters.LateAccessFilter相關(guān)聯(lián)。filter元素還包含兩個init-param子元素:一個定義 startTime參數(shù),另一個定義endTime參數(shù)。因為將要訪問filterRus主頁的人是程序員,考慮反常的時間范圍為上午2:00到10: 00之間。最后,filter-mapping元素使用值為/index.jsp的ulr-pattern子元素,將此過濾器與Web應(yīng)用主頁相關(guān)聯(lián)。參 看程序清單9-10。
            5)己用激活器serlvet。這個已經(jīng)在第2節(jié)介紹過,不再重復(fù)。
            當(dāng)這個Web應(yīng)用部署在一個外部服務(wù)器上且附加 了日志記錄過濾器后,客戶機對此Web應(yīng)用主頁的請求將在日志文件中產(chǎn)生一個項,如:“WARNING:  hacker6.filtersrus.com accessed http://www.filtersrus.com/filters/index.jsp on Oct 30,2001 9: 22:09 AM.”。

            程序清單9-9 LateAccessFilter.java
            package moreservlets.filters;

            import java.io.*;
            import javax.servlet.*;
            import javax.servlet.http.*;
            import java.util.*;
            import java.text.*;

            /** Filter that keeps track of accesses that occur
            * at unusual hours.
            */
            public class LateAccessFilter implements Filter {
              private FilterConfig config;
              private ServletContext context;
              private int startTime, endTime;
              private DateFormat formatter;
              public void doFilter(ServletRequest request,
                                   ServletResponse response,
                                   FilterChain chain)
                    throws ServletException, IOException {
                HttpServletRequest req = (HttpServletRequest)request;
                GregorianCalendar calendar = new GregorianCalendar();
                int currentTime = calendar.get(calendar.HOUR_OF_DAY);
                if (isUnusualTime(currentTime, startTime, endTime)) {
                  context.log("WARNING: " +
                  req.getRemoteHost() +
                  " accessed " +
                  req.getRequestURL() +
                  " on " +
                  formatter.format(calendar.getTime()));
                }
                chain.doFilter(request,response);
              }

              public void init(FilterConfig config)
                    throws ServletException {
                this.config = config;
                context = config.getServletContext();
                formatter =
                  DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
                DateFormat.MEDIUM);
                try {
                  startTime =
                    Integer.parseInt(config.getInitParameter("startTime"));
                  endTime =
                    Integer.parseInt(config.getInitParameter("endTime"));
                } catch(NumberFormatException nfe) { // Malformed or null
                  // Default: access at or after 10 p.m. but before 6 a.m.
                  // is considered unusual.
                  startTime = 22; // 10:00 p.m.
                  endTime = 6; // 6:00 a.m.
                }
              }

              public void destroy() {}

              // Is the current time between the start and end
              // times that are marked as abnormal access times?

              private boolean isUnusualTime(int currentTime,
                                            int startTime,
                                            int endTime) {
                // If the start time is less than the end time (i.e.,
                // they are two times on the same day), then the
                // current time is considered unusual if it is
                // between the start and end times.
                if (startTime < endTime) {
                  return((currentTime >= startTime) &&
                  (currentTime < endTime));
                }
                // If the start time is greater than or equal to the
                // end time (i.e., the start time is on one day and
                // the end time is on the next day), then the current
                // time is considered unusual if it is NOT between
                // the end and start times.
                else {
                  return(!isUnusualTime(currentTime, endTime, startTime));
                }
              }
            }


            程序清單9-10 web.xml(針對訪問時過濾器的摘錄)
            <?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>
                <!-- ... -->

                <!-- Register the name "LateAccessFilter" for
                    moreservlets.filter.LateAccessFilter.
                    Supply two initialization parameters:
                    startTime and endTime.
                -->
                <filter>
                  <filter-name>LateAccessFilter</filter-name>
                  <filter-class>
                    moreservlets.filters.LateAccessFilter
                  </filter-class>
                  <init-param>
                    <param-name>startTime</param-name>
                    <param-value>2</param-value>
                  </init-param>
                  <init-param>
                    <param-name>endTime</param-name>
                    <param-value>10</param-value>
                  </init-param>
                </filter>
                <!-- ... -->

                <!-- Apply LateAccessFilter to the home page. -->
                <filter-mapping>
                  <filter-name>LateAccessFilter</filter-name>
                  <url-pattern>/index.jsp</url-pattern>
                </filter-mapping>

                <!-- ... -->
            </web-app>

            posted on 2004-10-22 21:45 Khan 閱讀(723) 評論(1)  編輯 收藏 引用 所屬分類: Java

            評論

            # re: servlet和JSP過濾器Filter   回復(fù)  更多評論   

            網(wǎng)站提交的時候有些字符給腳本解釋器過濾了,大家不要貼代碼,自己小心看看
            2006-01-19 14:58 | Khan's Notebook
            久久亚洲精品无码AV红樱桃| 中文无码久久精品| 国产成人精品免费久久久久| 久久久久久久综合狠狠综合| 久久精品成人免费观看97| 一级做a爰片久久毛片人呢| 久久国产精品成人片免费| 久久亚洲精品人成综合网| 国色天香久久久久久久小说| 久久99热这里只有精品66| 亚洲国产成人乱码精品女人久久久不卡 | 欧美与黑人午夜性猛交久久久| 久久最近最新中文字幕大全| 久久er国产精品免费观看2| 国产午夜福利精品久久2021| 69久久精品无码一区二区| 国产∨亚洲V天堂无码久久久| 国产精品一久久香蕉国产线看观看 | 国产亚洲美女精品久久久久狼| 久久精品人成免费| 国产精品美女久久久| 国产精品成人精品久久久| 久久久综合香蕉尹人综合网| 久久夜色精品国产www| 久久久久久久久久久久久久| 亚洲AV日韩精品久久久久| 国产综合久久久久| 国产精品99久久久久久董美香| 怡红院日本一道日本久久 | 欧美精品丝袜久久久中文字幕 | 日韩美女18网站久久精品| 思思久久99热只有频精品66 | 国内精品久久久久久99蜜桃| 亚洲国产精品婷婷久久| 少妇被又大又粗又爽毛片久久黑人| 久久国语露脸国产精品电影| 久久精品国产亚洲av麻豆小说 | 99久久精品免费国产大片| 亚洲国产一成久久精品国产成人综合| 中文字幕亚洲综合久久菠萝蜜| 97久久精品午夜一区二区|