Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 11Listener和Filter

11Listener和Filter

編輯:關於Android編程

Listener
Listener是Servlet的監聽器,它可以監聽客戶端的請求、服務端的操作等。通過監聽器,可以自動激發一些操作,比如監聽在線的用戶的數量。當增加一個HttpSession時,就激發sessionCreated(HttpSessionEvent se)方法,這樣就可以給在線人數加1。Javax.servlet中定義了三類監聽器:ServletContex相關、ServletRequest相關、和HttpSession相關的監聽器。

ServletContext相關監聽器:
ServletContextAttributeListener監聽對ServletContext屬性的操作,比如增加、刪除、修改屬性。
void attributeAdded(ServletContextAttributeEvent scab):在servlet上下文增加了一個屬性時觸發;
void attributeRemoved(ServletContextAttributeEvent scab):在servlet上下文移除一個已存在的屬性時觸發;
void attributeReplaced(ServletContextAttributeEvent scab):在servlet上下文替換一個已存在的屬性時觸發。

ServletContextListener監聽ServletContext。接收到web應用中servlet上下文載入或銷毀的事件通知。
當創建ServletContext時,激發contextInitialized(ServletContextEvent sce)方法;所有的ServletContextListener都將先於filter和servlet的初始化前被通知。
當銷毀ServletContext時,激發contextDestroyed(ServletContextEvent sce)方法。所有的filter和servlet都將在ServletContextListener被通知前被destory。

事實上,contextListener、filter、servlet的初始化順序依次是listener、filter、servlet。

ServletRequest相關監聽器
ServletRequestListener:當你希望接收到各種request請求進入(coming in)或離開(out of)一個web部件(component)的消息時,你可以通過實現這個接口來完成。當一個request開始進入每一個web應用的第一個servlet或filter時,將觸發進入(coming in)web應用事件,當一個request離開最後一個servlet或filter鏈的第一個filter時,將觸發一個離開(out of)web應用事件。(注意filter鏈的執行順序)
該監聽器定義了下面兩個方法:
void requestDestroyed(ServletRequestEvent sre): request將離開一個web應用;
void requestInitialized(ServletRequestEvent sre) :request 將進入一個web應用。

ServletRequestAttributeListener:當你希望接收到request的屬性變更事件時,可以通過實現這個接口來完成。變更通知只在request處於web應用中的時候發出。Request處於一個web應用指的是,從一個request進入(coming in)web應用到離開(out of)web應用之間的時間。
該監聽器定義了下面方法:
void attributeAdded(ServletRequestAttributeEvent srae): 向一個request裡面增加一個屬性時觸發;
void attributeRemoved(ServletRequestAttributeEvent srae): 從一個request裡面移除一個屬性時觸發;
void attributeReplaced(ServletRequestAttributeEvent srae): 從一個request裡面替換一個屬性時觸發。

HttpSession相關監聽器:
HttpSessionListener監聽HttpSession的操作。
當創建一個Session時,激發session Created(HttpSessionEvent se)方法;
當銷毀一個Session時,激發sessionDestroyed(HttpSessionEvent se)方法。

HttpSessionAttributeListener監聽HttpSession中的屬性的操作。
當在Session增加一個屬性時,激發attributeAdded(HttpSessionBindingEvent se) 方法;
當在Session刪除一個屬性時,激發attributeRemoved(HttpSessionBindingEvent se)方法;
當在Session屬性被重新設置時,激發attributeReplaced(HttpSessionBindingEvent se) 方法。

如何指定應用事件監聽程序
應用事件監聽器程序是建立或修改servlet環境或會話對象時通知的類。它們是servlet規范的版本2.3中的新內容。這裡只簡單地說明用來向Web應用注冊一個監聽程序的web.xml的用法。
注冊一個監聽程序涉及在web.xml的web-app元素內放置一個listener元素。在listener元素內,listener-class元素列出監聽程序的完整的限定類名,如下所示:

package.ListenerClass


雖然listener元素的結構很簡單,但請不要忘記,必須正確地給出web-app元素內的子元素的次序。
*******************
listener元素位於所有的servlet 元素之前以及所有filter-mapping元素之後。此外,因為應用生存期監聽程序是serlvet規范的2.3版本中的新內容,所以必須使用 web.xml DTD的2.3版本,而不是2.2版本。
*******************
例如,程序清單5-20給出一個名為ContextReporter的簡單的監聽程序,它實現了ServletContextListener接口,只要Web應用的Servlet-Context建立(如裝載Web應用)或消除(如服務器關閉)時,它就在標准輸出上顯示一條消息。程序清單5-21給出此監聽程序注冊所需要的web.xml文件的一部分。
程序清單5-20 ContextReporterjava
package moreservlets;


import javax.servlet.*;
import java.util.*;
public class ContextReporter implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
//ServletContextEvent的實例的getServletContext()方法返回SevletContext對象
ServletContext servletContext = event.getServletContext();


System.out.println("Context created on " +
new Date() + ".");
}
public void contextDestroyed(ServletContextEvent event) {
System.out.println("Context destroyed on " +
new Date() + ".");
}
}
程序清單5-21 web.xml(聲明一個監聽程序的摘錄)

PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">




package.ListenerClass


...




Filter
Servlet過濾器是小型的Web組建,它可以攔截請求和響應,以便查看,提取或以某種方式操作正在客戶機和服務器之間交換的數據。我們可以用過濾器解決中文編碼問題。它先於與之相關的servlet或jsp頁面運行在服務器上,過濾器可以附加到一個或多個servlet或jsp頁面上,並且可以檢查進入這些資源的請求信息。過濾器可以做如下選擇:
以常規的方式調用資源(即調用servlet或jsp頁面)
利用修改過的請求信息調用資源。
調用資源,但在發送響應道客戶機前對其進行修改。
組織該資源調用,代之以轉到其他的資源。


過濾器通過Web部署描述文件web.xml中的XML元素來聲明,這樣允許添加和刪除過濾器,而無需改動任何應用程序代碼或JSP頁面。
過濾器首先是根據url-pattern來判斷是用哪個過濾器,
如果url-pattern符合多個過濾器的時候,就根據過濾器在web.xml中配置的先後順序來依次執行過濾器。


如何實現Filter
要想開發一個過濾器,就必須實現javax.servlet.Filter接口,在Filter接口中定義了init,doFilter,destroy方法。下面是一個過濾器走過的流程:
init(FilterConfig filterConfig)
這個方法由Web容器在過濾器實例化之後被調用。用於執行本過濾器的初始化操作,通過參數FilterConfig可以得到這個過濾器的所有配置的參數。它只在此過濾器第一次初始化時執行,不是每次調用過濾器都執行它。FilterConfig對象具有一個getInitParameter方法,它能夠訪問部署描述符文件(web.xml)中分配的過濾器初始化參數。




doFilter(ServletRequest request,ServletResponse response,FilterChain chain)
在該方法放入過濾行為,由鏈路終端用戶請求,Web容器將會在每個request/reponse鏈路中調用doFilter()方法。通過傳遞FilterChain對象,doFilter()方法可以將request和reponse對象傳遞到鏈路中的下一個實體,就是說doFilter()方法就是具體的過濾處理代碼,同時它可以決定被浏覽器處理後下一步要進行的操作。
DoFilter的最後一個參數為FilterChain對象,對此對象調用對象的doFilter方法以激活下一個相關的過濾器。如果沒有另一個過濾器與servlet或jsp頁面關聯,則servlet或jsp頁面被激活。


destroy(),這個方法由Web容器負責調用。通常在銷毀Filter對象的實例之前調用destory()方法,因為它是和init()方法相對應,所以這個方法主要用戶釋放init()中申請的資源。


Filter在web.xml中配置和部署
Filter的配置和部署工作是在Web應用的web.xml配置文件中進行的。在Filter的配置中應用到兩個配置元素:
...
filter元素向系統注冊一個過濾對象,它包含的子元素有:
filter-name用於定義Filter的名稱。
Filter-class用於定義這個Filter的具體實現對象。
init-param 這是一個可選的元素,它定義可利用FilterConfig的getInitParameter方法讀取的初始化參數。單個過濾器元素可包含多個init-param元素。


...
filter-mapping元素指定該過濾對象所應用的URL。它包含的子元素有:
其中filter-name用於引用在filter元素中定義的filter名稱。
url-pattern 此元素聲明一個以斜槓(/)開始的模式,用於指明與URL相匹配的方式,只有相匹配的請求才會被Filter所處理。/*表示處理所有的請求,/*.jsp表示處理所有jsp頁面的請求。/manage/*表示對/manage下的所有請求。如果希望過濾器適用於多個模式,可重復整個filter-mapping元素。
servlet-name 此元素給出一個名稱,此名稱必須與利用servlet元素給予servlet或JSP頁面的名稱相匹配。不能給單個filter-mapping元素提供多個servlet-name元素項。如果希望過濾器適合於多個servlet名,可重復這個filter-mapping元素。
例如: 字符編碼過濾器

SimpleFilter
com.darkmi.filter.SimpleFilter

encoding
UTF-8




SimpleFilter

/*

package cn.hxex.tutorial;
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.UnavailableException;


public class SetCharacterEncodingFilter implements Filter {
protected String encoding = null;
protected FilterConfig filterConfig = null;
protected boolean ignore = true;


public void destroy() {
this.encoding = null;
this.filterConfig = null;
}


public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// Conditionally select and set the character encoding to be used
if (ignore || (request.getCharacterEncoding() == null)) {
String encoding = selectEncoding(request);
if (encoding != null)
//設置對客戶端請求進行重新編碼的編碼,
request.setCharacterEncoding(encoding);
}


// Pass control on to the next filter
chain.doFilter(request, response);
}


public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
String value = filterConfig.getInitParameter("ignore");
if (value == null)
this.ignore = true;
else if (value.equalsIgnoreCase("true"))
this.ignore = true;
else if (value.equalsIgnoreCase("yes"))
this.ignore = true;
else
this.ignore = false;
}


// ------------------------------------------------------
//Protected Methods
protected String selectEncoding(ServletRequest request) {
return (this.encoding);
}
}



使浏覽器不緩存頁面的過濾器:
import javax.servlet. * ;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


/**
* 用於的使 Browser 不緩存頁面的過濾器
*/
public class ForceNoCacheFilter implements Filter {


public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException
{
((HttpServletResponse) response).setHeader( " Cache-Control " , " no-cache " );
((HttpServletResponse) response).setHeader( " Pragma " , " no-cache " );
((HttpServletResponse) response).setDateHeader ( " Expires " , - 1 );
filterChain.doFilter(request, response);
}


public void destroy() {
}


public void init(FilterConfig filterConfig) throws ServletException {
}
}


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved