JAVA中的過濾器與監聽器
過濾器
什麼是過濾器
過濾器就是 Servlet 的進階特性之一,就是一個具有攔截/過濾功能的一個東西,在生活中過濾器可以是香煙濾嘴,濾紙,淨水器,空氣淨化器等,在 Web 中僅僅是一個實作了 Filter 接口的 Java 類而已。
特點:雙向,攔截請求,攔截響應
作用:
過濾器可以對所有的請求或者響應做攔截操作
Web 中過濾器的作用:
1.可以在請求資源之前設定請求的編碼
2.可以進行登入校驗
3.可以進行請求參數的内容的過濾
4.資料壓縮 / 資料加密 / 資料格式的轉換
5.可以設定浏覽器相關的資料
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL1EFVPBTQ65EeRpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZwpmL0QTM0UjMwcDM4ITOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
1、Filter工作原理(執行流程)
當用戶端發出Web資源的請求時,Web伺服器根據應用程式配置檔案設定的過濾規則進行檢查,若客戶請求滿足過濾規則,則對客戶請求/響應進行攔截,對請求頭和請求資料進行檢查或改動,并依次通過過濾器鍊,最後把請求/響應交給請求的Web資源處理。請求資訊在過濾器鍊中可以被修改,也可以根據條件讓請求不發往資源處理器,并直接向客戶機發回一個響應。當資源處理器完成了對資源的處理後,響應資訊将逐級逆向傳回。同樣在這個過程中,使用者可以修改響應資訊,進而完成一定的任務。
伺服器會按照web.xml中過濾器定義的先後循序組裝成一條鍊,然後一次執行其中的doFilter()方法。執行的順序應該就是執行第一個過濾器的chain.doFilter()之前的代碼,第二個過濾器的chain.doFilter()之前的代碼,請求的資源,第二個過濾器的chain.doFilter()之後的代碼,第一個過濾器的chain.doFilter()之後的代碼,最後傳回響應。
過濾器的執行流程:
執行第一個過濾器的chain.doFilter()之前的代碼——>第二個過濾器的chain.doFilter()之前的代碼——>……——>第n個過濾器的chain.doFilter()之前的代碼——>所請求servlet的service()方法中的代碼——>所請求servlet的doGet()或doPost()方法中的代碼——>第n個過濾器的chain.doFilter()之後的代碼——>……——>第二個過濾器的chain.doFilter()之後的代碼——>第一個過濾器的chain.doFilter()之後的代碼。
過濾器生命周期的四個階段:
1、執行個體化:Web容器在部署Web應用程式時對所有過濾器進行執行個體化。Web容器回調它的無參構造方法。2、初始化:執行個體化完成之後,馬上進行初始化工作。Web容器回調init()方法。
3、過濾:請求路徑比對過濾器的URL映射時。Web容器回調doFilter()方法——主要的工作方法。
4、銷毀: Web容器在解除安裝Web應用程式前,Web容器回調destroy()方法。
Servlet過濾器開發步驟:
1、建立實作javax.servlet.Filter接口的類。
2、過濾器的xml配置。
Servlet過濾器API
Servlet過濾器API包含了3個接口,它們都在javax.servlet包中,分别是Filter接口FilterChain接口和FilterConfig接口。
public Interface Filter所有的過濾器都必須實作Filter接口。該接口定義了init,doFilter0,destory()三個方法:
(1) public void init (FilterConfig filterConfig)
當開始使用servlet過濾器服務時,Web容器調用此方法一次,為服務準備過濾器;然後在需要使用過濾器的時候調用doFilter(),傳送給此方法的FilterConfig對象,包含servlet過濾器的初始化參數。
(2)public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)
每個過濾器都接受目前的請求和響應,且FilterChain過濾器鍊中的過濾器(應該都是符合條件的)都會被執行。doFilter方 法中,過濾器可以對請求和響應做它想做的一切,通過調用他們的方法收集資料,或者給對象添加新的行為。過濾器通過傳送至 此方法的FilterChain參數,調用chain.doFilterO将控制權傳送給下一個過濾器。當這個調用傳回後,過濾器可以在它的 Filter方法的最後對響應做些其他的工作。如果過濾器想要終止請求的處理或得到對響應的完全控制,則可以不調用下一個過濾 器,而将其重定向至其它一些頁面。當鍊中的最後一個過濾器調用chain.doFilterO方法時,将運作最初請求的Servlet。
(3)public void destroy()
一旦doFilterO方法裡的所有線程退出或已逾時,容器調用
此方法。伺服器調用destoryO以指出過濾器已結束服務,用于釋
放過濾器占用的資源。
public interface FilterChain
public void doFilter(ServletRequest request,ServletResponse response)
此方法是由Servlet容器提供給開發者的,用于對資源請求過濾鍊的依次調用,通過FilterChain調用過濾鍊中的下一個過濾 器,如果是最後一個過濾器,則下一個就調用目标資源。
public interface FilterConfig
FilterConfig接口檢索過濾器名、初始化參數以及活動的Servlet上下文。該接口提供了以下4個方法:
(1)public java.1ang.String getFilterName0
傳回web.xml部署檔案中定義的該過濾器的名稱。
(2)public ServletContext getServletContextO
傳回調用者所處的servlet上下文。
(3)public java.1ang.String getlnitParameter(java.1ang.String name)
傳回過濾器初始化參數值的字元串形式,當參數不存在時,傳回nul1.name是初始化參數名。
(4)public java.util.Enumeration getlnitParameterNames()
以Enumeration形式傳回過濾器所有初始化參數值,如果沒有初始化參數,傳回為空。
監聽器
什麼是監聽器:
監聽器用于監聽web應用中某些對象、資訊的建立、銷毀、增加,修改,删除等動作的發生,然後作出相應的響應處理。當範圍對象的狀态發生變化的時候,伺服器自動調用監聽器對象中的方法。常用于統計線上人數和線上使用者,系統加載時進行資訊初始化,統計網站的通路量等等。
作用:
1.監聽 web 應用的建立和銷毀(除了對web應用的監聽外,還能監聽session和request的生命周期,以及他們的attribute發生的變化)
2.attribute發生的變化。
示例:用監聽器統計網站線上人數
@WebListener
public class OnlineListener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent se) {
System.out.println("OnlineListener.attributeAdded");
String name = se.getName();
//登入使用者的session發生變化
if("account".equals(name)){
ServletContext application = se.getSession().getServletContext();
int online_num = application.getAttribute("online_num") == null ? 0 : (Integer) application.getAttribute("online_num");
System.out.println("online_num = " + online_num);
online_num++;
application.setAttribute("online_num",online_num);
}
}
@Override
public void attributeRemoved(HttpSessionBindingEvent se) {
System.out.println("OnlineListener.attributeRemoved");
String name = se.getName();
//退出 使用者的session發生變化
if("account".equals(name)){
ServletContext application = se.getSession().getServletContext();
int online_num = application.getAttribute("online_num") == null ? 0 : (Integer) application.getAttribute("online_num");
System.out.println("online_num = " + online_num);
online_num--;
application.setAttribute("online_num",online_num);
}
}
}