Listener是Servlet的監(jiān)聽(tīng)器,它可以監(jiān)聽(tīng)客戶(hù)端的請(qǐng)求、服務(wù)端的操作等。通過(guò)監(jiān)聽(tīng)器,可以自動(dòng)激發(fā)一些操作,比如監(jiān)聽(tīng)在線(xiàn)的用戶(hù)的數(shù)量。當(dāng)增加一個(gè)HttpSession時(shí),就激發(fā)sessionCreated(HttpSessionEvent se)方法,這樣就可以給在線(xiàn)人數(shù)加1。常用的監(jiān)聽(tīng)接口有以下幾個(gè):
ServletContextListener監(jiān)聽(tīng)ServletContext。當(dāng)創(chuàng)建ServletContext時(shí),激發(fā) contextInitialized(ServletContextEvent sce)方法;當(dāng)銷(xiāo)毀ServletContext時(shí),激發(fā)contextDestroyed(ServletContextEvent sce)方法。
ServletContextAttributeListener監(jiān)聽(tīng)對(duì)ServletContext屬性的操作,比如增加、刪除、修改屬性。
HttpSessionListener監(jiān)聽(tīng)HttpSession的操作。當(dāng)創(chuàng)建一個(gè)Session時(shí),激發(fā)session Created(HttpSessionEvent se)方法;當(dāng)銷(xiāo)毀一個(gè)Session時(shí),激發(fā)sessionDestroyed (HttpSessionEvent se)方法。
HttpSessionAttributeListener監(jiān)聽(tīng)HttpSession中的屬性的操作。當(dāng)在Session增加一個(gè)屬性時(shí),激發(fā) attributeAdded(HttpSessionBindingEvent se) 方法;當(dāng)在Session刪除一個(gè)屬性時(shí),激發(fā)attributeRemoved(HttpSessionBindingEvent se)方法;當(dāng)在Session屬性被重新設(shè)置時(shí),激發(fā)attributeReplaced(HttpSessionBindingEvent se) 方法。
下面我們開(kāi)發(fā)一個(gè)具體的例子,這個(gè)監(jiān)聽(tīng)器能夠統(tǒng)計(jì)在線(xiàn)的人數(shù)。
程序源代碼:
package com.dr.web.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
publicclass UserCountListener implements ServletContextListener,
HttpSessionListener {
//每個(gè)web應(yīng)用都有且僅有一個(gè)ServletContext對(duì)象,這個(gè)對(duì)象在所有的Servlet都可以使用。
/**
* 因?yàn)橐粋€(gè)web應(yīng)用就一個(gè)ServletContext 對(duì)象,因此可以使用ServletContext 來(lái)做一些全局性的屬性設(shè)置等。
* 比如網(wǎng)站訪(fǎng)問(wèn)計(jì)數(shù)器等等
*
*
* ServletContext 是一個(gè)應(yīng)用程序與Web容器(tomcat之類(lèi))交互的接口,同時(shí)它也是管理應(yīng)用程序資源的對(duì)象,
通過(guò)它可以讀取web.xml中一些配置,如<context-param>中的信息,讀取應(yīng)用中的資源等。
Session 是一個(gè)會(huì)話(huà)對(duì)象,也就是說(shuō)當(dāng)客戶(hù)端訪(fǎng)問(wèn)服務(wù)器頁(yè)面時(shí),它才產(chǎn)生,
原理是服務(wù)器對(duì)每個(gè)客戶(hù)端產(chǎn)生一個(gè)sessionid值,并把它也保存在客戶(hù)端,
每次請(qǐng)求時(shí)驗(yàn)證這個(gè)sessionid是否是創(chuàng)建了sessionid的客戶(hù)端,在服務(wù)器端對(duì)應(yīng)這個(gè)sessionid會(huì)創(chuàng)建一個(gè)緩存區(qū),
存儲(chǔ)一些相關(guān)信息,程序員可以操作,如被用于購(gòu)物車(chē),存儲(chǔ)用戶(hù)信息等,這個(gè)區(qū)域只有對(duì)特定用戶(hù)有訪(fǎng)問(wèn)權(quán)限,對(duì)其他客戶(hù)是拒絕訪(fǎng)問(wèn)的,這就是一個(gè)會(huì)話(huà)。
Request 是一個(gè)請(qǐng)求對(duì)象,也就是說(shuō)它的生命很短暫,只在一個(gè)請(qǐng)求中存在,如一個(gè)頁(yè)面到另一個(gè)頁(yè)面,
一個(gè)頁(yè)面到servlet或action,一個(gè)servlet或action到jsp頁(yè)面等,你可以用它的setAttribute方法傳遞需要的信息(對(duì)象),驗(yàn)證請(qǐng)求方的信息,獲得請(qǐng)求方發(fā)過(guò)來(lái)的文件內(nèi)容等。
*/
private ServletContext sc;
publicvoid contextDestroyed(ServletContextEvent arg0) {
}
publicvoid contextInitialized(ServletContextEvent event) {
ServletContext sc = event.getServletContext();
sc.setAttribute("Users", new Integer(0));
this.sc = sc;
}
publicvoid sessionCreated(HttpSessionEvent event) {//在線(xiàn)
System.out.println("new user login our web site");
Integer users = (Integer)sc.getAttribute("Users");
sc.setAttribute("Users", ++users);
}
publicvoid sessionDestroyed(HttpSessionEvent event) {
Integer users = (Integer)sc.getAttribute("Users");
sc.setAttribute("Users", --users);
}
}
Web.xml中配置如下:
<listener>
<listener-class>com.dr.web.listener.UserCountListener</listener-class>
</listener>
在UserCountListener里,用users代表當(dāng)前在線(xiàn)的人數(shù),UserCountListener將在Web服務(wù)器啟動(dòng)時(shí)自動(dòng)執(zhí)行。當(dāng)UserCountListener構(gòu)造好后,把users設(shè)置為 0。每增加一個(gè)Session,UserCountListener會(huì)自動(dòng)調(diào)用sessionCreated(HttpSessionEvent event)方法;每銷(xiāo)毀一個(gè)Session,UserCountListener會(huì)自動(dòng)調(diào)用 sessionDestroyed(HttpSessionEvent se)方法。當(dāng)調(diào)用sessionCreated(HttpSessionEvent event)方法時(shí),說(shuō)明又有一個(gè)客戶(hù)在請(qǐng)求,此時(shí)使在線(xiàn)的人數(shù)(users)加1,并且把user寫(xiě)到ServletContext中。 ServletContext的信息是所有客戶(hù)端共享的,這樣,每個(gè)客戶(hù)端都可以讀取到當(dāng)前在線(xiàn)的人數(shù)。
運(yùn)行結(jié)果:
考慮并發(fā),什么意思?如果一秒鐘內(nèi)同時(shí)有2人進(jìn)入網(wǎng)站,監(jiān)聽(tīng)不到?