JavaWeb學習篇之----Servlet過濾器Filter和監聽器

首先來看一下Servlet的過濾器內容:


一、Servlet過濾器的概念:

***************************************************************************************
Servlet過濾器是在Java Servlet規範2.3中定義的,它能夠對Servlet容器的請求和響應對象進行檢查和修改。   
Servlet過濾器本身並不產生請求和響應對象,它只能提供過濾作用。Servlet過期能夠在Servlet被調用之前檢查Request對象,修改Request Header和Request內容;在Servlet被調用之後檢查Response對象,修改Response Header和Response內容。
Servlet過期負責過濾的Web組件可以是Servlet、JSP或者HTML文件。 
***************************************************************************************

二、Servlet過濾器的特點:
***************************************************************************************
A.Servlet過濾器可以檢查和修改ServletRequest和ServletResponse對象
B.Servlet過濾器可以被指定和特定的URL關聯,只有當客戶請求訪問該URL時,纔會觸發過濾器
C.Servlet過濾器可以被串聯在一起,形成管道效應,協同修改請求和響應對象
***************************************************************************************

三、Servlet過濾器的作用:
***************************************************************************************
A.查詢請求並作出相應的行動。
B.阻塞請求-響應對,使其不能進一步傳遞。
C.修改請求的頭部和數據。用戶可以提供自定義的請求。
D.修改響應的頭部和數據。用戶可以通過提供定製的響應版本實現。
E.與外部資源進行交互。
***************************************************************************************

四、Servlet過濾器的適用場合:
***************************************************************************************
A.認證過濾
B.登錄和審覈過濾
C.圖像轉換過濾 
D.數據壓縮過濾 
E.加密過濾 
F.令牌過濾 
G.資源訪問觸發事件過濾 
H.XSL/T過濾 
I.Mime-type過濾
***************************************************************************************

五、Servlet過濾器接口的構成:
***************************************************************************************
所有的Servlet過濾器類都必須實現javax.servlet.Filter接口。這個接口含有3個過濾器類必須實現的方法:
A.init(FilterConfig):
這是Servlet過濾器的初始化方法,Servlet容器創建Servlet過濾器實例後將調用這個方法。在這個方法中可以讀取web.xml文件中Servlet過濾器的初始化參數
B.doFilter(ServletRequest,ServletResponse,FilterChain):
這個方法完成實際的過濾操作,當客戶請求訪問於過濾器關聯的URL時,Servlet容器將先調用過濾器的doFilter方法。FilterChain參數用於訪問後續過濾器
C.destroy():
Servlet容器在銷燬過濾器實例前調用該方法,這個方法中可以釋放Servlet過濾器佔用的資源
***************************************************************************************

六、Servlet過濾器的創建步驟:
***************************************************************************************
A.實現javax.servlet.Filter接口
B.實現init方法,讀取過濾器的初始化函數
C.實現doFilter方法,完成對請求或過濾的響應
D.調用FilterChain接口對象的doFilter方法,向後續的過濾器傳遞請求或響應
E.銷燬過濾器
***************************************************************************************

七、Servlet過濾器對請求的過濾:
***************************************************************************************
A.Servlet容器創建一個過濾器實例
B.過濾器實例調用init方法,讀取過濾器的初始化參數
C.過濾器實例調用doFilter方法,根據初始化參數的值判斷該請求是否合法
D.如果該請求不合法則阻塞該請求
E.如果該請求合法則調用chain.doFilter方法將該請求向後續傳遞
***************************************************************************************

八、Servlet過濾器對響應的過濾:
***************************************************************************************
A.過濾器截獲客戶端的請求
B.重新封裝ServletResponse,在封裝後的ServletResponse中提供用戶自定義的輸出流
C.將請求向後續傳遞
D.Web組件產生響應
E.從封裝後的ServletResponse中獲取用戶自定義的輸出流
F.將響應內容通過用戶自定義的輸出流寫入到緩衝流中
G.在緩衝流中修改響應的內容後清空緩衝流,輸出響應內容
***************************************************************************************

九、Servlet過濾器的發佈:
***************************************************************************************
A.發佈Servlet過濾器時,必須在web.xml文件中加入<filter>元素和<filter-mapping>元素。
B.<filter>元素用來定義一個過濾器:
屬性                   含義
filter-name    指定過濾器的名字
filter-class    指定過濾器的類名
init-param    爲過濾器實例提供初始化參數,可以有多個
C.<filter-mapping>元素用於將過濾器和URL關聯:
屬性                     含義
filter-name    指定過濾器的名字
url-pattern    指定和過濾器關聯的URL,爲”/*”表示所有URL
***************************************************************************************

十一、Servlet過濾器使用的注意事項
***************************************************************************************
A.由於Filter、FilterConfig、FilterChain都是位於javax.servlet包下,並非HTTP包所特有的,所以其中所用到的請求、響應對象ServletRequest、ServletResponse在使用前都必須先轉換成HttpServletRequest、HttpServletResponse再進行下一步操作。
B.在web.xml中配置Servlet和Servlet過濾器,應該先聲明過濾器元素,再聲明Servlet元素
C.如果要在Servlet中觀察過濾器生成的日誌,應該確保在server.xml的localhost對應的<host>元素中配置如下<logger>元素:
<Logger className = “org.apache.catalina.logger.FileLogger”
directory = “logs”prefix = “localhost_log.”suffix=”.txt”
timestamp = “true”/>

***************************************************************************************

十二、一個實例

首先來看一下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中註冊的是先註冊日誌過濾器的,然後再註冊


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


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


下面在來看一下Servlet的監聽器


Servlet監聽器用於監聽一些重要事件的發生,監聽器對象可以在事情發生前、發生後可以做一些必要的處理。下面將介紹幾種常用的監聽器,以及它們都適合運用於那些環境。 


分類及介紹:
1.  ServletContextListener:用於監聽WEB 應用啓動和銷燬的事件,監聽器類需要實現javax.servlet.ServletContextListener 接口。 

public class QuartzListener implements ServletContextListener {  
    private Logger logger = LoggerFactory.getLogger(QuartzListener.class);  
  
    public void contextInitialized(ServletContextEvent sce) {  
    }  
  
    /** 
     *在服務器停止運行的時候停止所有的定時任務 
     */  
    @SuppressWarnings("unchecked")  
    public void contextDestroyed(ServletContextEvent arg0) {  
        try {  
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();  
            List<JobExecutionContext> jobList = scheduler.getCurrentlyExecutingJobs();  
            for (JobExecutionContext jobContext : jobList) {  
                Job job = jobContext.getJobInstance();  
                if (job instanceof InterruptableJob) {  
                    ((InterruptableJob) job).interrupt();  
                }  
            }  
            scheduler.shutdown();  
        } catch (SchedulerException e) {  
            logger.error("shut down scheduler happened error", e);  
        }  
    }  
}  


 
2.  ServletContextAttributeListener:用於監聽WEB應用屬性改變的事件,包括:增加屬性、刪除屬性、修改屬性,監聽器類需要實現javax.servlet.ServletContextAttributeListener接口。 

3.  HttpSessionListener:用於監聽Session對象的創建和銷燬,監聽器類需要實現javax.servlet.http.HttpSessionListener接口或者javax.servlet.http.HttpSessionActivationListener接口,或者兩個都實現。

/** 
 *  
 * 會話監聽器 
 * <p /> 
 * 
 */  
public class SessionListener implements HttpSessionListener {  
  
    @Override  
    public void sessionCreated(HttpSessionEvent arg0) {  
  
    }  
  
    @Override  
    public void sessionDestroyed(HttpSessionEvent event) {  
        HttpSession session = event.getSession();  
        User user = (BrsSession) session.getAttribute("currUser");  
        if (user != null) {  
            //TODO something  
        }  
    }  
  
}  


4.  HttpSessionActivationListener:用於監聽Session對象的鈍化/活化事件,監聽器類需要實現javax.servlet.http.HttpSessionListener接口或者javax.servlet.http.HttpSessionActivationListener接口,或者兩個都實現。 

5.  HttpSessionAttributeListener:用於監聽Session對象屬性的改變事件,監聽器類需要實現javax.servlet.http.HttpSessionAttributeListener接口。 

部署: 
       監聽器的部署在web.xml文件中配置,在配置文件中,它的位置應該在過濾器的後面Servlet的前面

 

web.xml配置文件:

 

<!-- Quartz監聽器 -->  
<listener>  
    <listener-class>  
        com.flyer.lisenter.QuartzListener  
    </listener-class>  
</listener> 

發佈了313 篇原創文章 · 獲贊 49 · 訪問量 87萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章