HttpSessionListener 和HttpSessionBindingListener的區(qū)別(單點(diǎn)登陸時(shí)有用)
8.1. 使用HttpSessionListener
編寫(xiě)一個(gè)OnlineUserListener。
package anni;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSessionEvent;
public class OnlineUserListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent event) {
}
public void sessionDestroyed(HttpSessionEvent event) {
HttpSession session = event.getSession();
ServletContext application = session.getServletContext();
// 取得登錄的用戶(hù)名
String username = (String) session.getAttribute("username");
// 從在線(xiàn)列表中刪除用戶(hù)名
List onlineUserList = (List) application.getAttribute("onlineUserList");
onlineUserList.remove(username);
System.out.println(username + "超時(shí)退出。");
}
}
OnlineUserListener實(shí)現(xiàn)了HttpSessionListener定義的兩個(gè)方法:sessionCreated()和 sessionDestroyed()。這兩個(gè)方法可以監(jiān)聽(tīng)到當(dāng)前應(yīng)用中session的創(chuàng)建和銷(xiāo)毀情況。我們這里只用到 sessionDestroyed()在session銷(xiāo)毀時(shí)進(jìn)行操作就可以。
從HttpSessionEvent中獲得即將銷(xiāo)毀的session,得到session中的用戶(hù)名,并從在線(xiàn)列表中刪除。最后一句向console打印一條信息,提示操作成功,這只是為了調(diào)試用,正常運(yùn)行時(shí)刪除即可。
為了讓監(jiān)聽(tīng)器發(fā)揮作用,我們將它添加到web.xml中:
<listener>
<listener-class>anni.OnlineUserListener</listener-class>
</listener>
以下兩種情況下就會(huì)發(fā)生sessionDestoryed(會(huì)話(huà)銷(xiāo)毀)事件:
-
執(zhí)行session.invalidate()方法時(shí)。
既然LogoutServlet.java中執(zhí)行session.invalidate()時(shí),會(huì)觸發(fā)sessionDestory()從在線(xiàn)用戶(hù) 列表中清除當(dāng)前用戶(hù),我們就不必在LogoutServlet.java中對(duì)在線(xiàn)列表進(jìn)行操作了,所以L(fǎng)ogoutServlet.java的內(nèi)容現(xiàn)在是 這樣。
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
// 銷(xiāo)毀session
request.getSession().invalidate();
// 成功
response.sendRedirect("index.jsp");
}
-
如果用戶(hù)長(zhǎng)時(shí)間沒(méi)有訪(fǎng)問(wèn)服務(wù)器,超過(guò)了會(huì)話(huà)最大超時(shí)時(shí)間,服務(wù)器就會(huì)自動(dòng)銷(xiāo)毀超時(shí)的session。
會(huì)話(huà)超時(shí)時(shí)間可以在web.xml中進(jìn)行設(shè)置,為了容易看到超時(shí)效果,我們將超時(shí)時(shí)間設(shè)置為最小值。
<session-config>
<session-timeout>1</session-timeout>
</session-config>
時(shí)間單位是一分鐘,并且只能是整數(shù),如果是零或負(fù)數(shù),那么會(huì)話(huà)就永遠(yuǎn)不會(huì)超時(shí)。
對(duì)應(yīng)例子在08-01,為了驗(yàn)證OnlineUserListener是否能正常執(zhí)行,我們可以登錄兩個(gè)用戶(hù),其中一個(gè)點(diǎn)擊注銷(xiāo),另一個(gè)等待一分鐘,然后可以在console中看到輸出的信息。

8.2. 使用HttpSessionBindingListener
HttpSessionBindingListener雖然叫做監(jiān)聽(tīng)器,但使用方法與HttpSessionListener完全不同。我們實(shí)際看一下它是如何使用的。
我們的OnlineUserBindingListener實(shí)現(xiàn)了HttpSessionBindingListener接口,接口中共定義了兩個(gè)方法:valueBound()和valueUnbound(),分別對(duì)應(yīng)數(shù)據(jù)綁定,和取消綁定兩個(gè)事件。
所謂對(duì)session進(jìn)行數(shù)據(jù)綁定,就是調(diào)用session.setAttribute()把HttpSessionBindingListener保存進(jìn)session中。我們?cè)贚oginServlet.java中進(jìn)行這一步。
// 把用戶(hù)名放入在線(xiàn)列表
session.setAttribute("onlineUserBindingListener", new OnlineUserBindingListener(username));
這就是HttpSessionBindingListener和HttpSessionListener之間的最大區(qū)別: HttpSessionListener只需要設(shè)置到web.xml中就可以監(jiān)聽(tīng)整個(gè)應(yīng)用中的所有session。 HttpSessionBindingListener必須實(shí)例化后放入某一個(gè)session中,才可以進(jìn)行監(jiān)聽(tīng)。
從監(jiān)聽(tīng)范圍上比較,HttpSessionListener設(shè)置一次就可以監(jiān)聽(tīng)所有session,HttpSessionBindingListener通常都是一對(duì)一的。
正是這種區(qū)別成就了HttpSessionBindingListener的優(yōu)勢(shì),我們可以讓每個(gè)listener對(duì)應(yīng)一個(gè)username,這樣 就不需要每次再去session中讀取username,進(jìn)一步可以將所有操作在線(xiàn)列表的代碼都移入listener,更容易維護(hù)。
valueBound()方法的代碼如下:
public void valueBound(HttpSessionBindingEvent event) {
HttpSession session = event.getSession();
ServletContext application = session.getServletContext();
// 把用戶(hù)名放入在線(xiàn)列表
List onlineUserList = (List) application.getAttribute("onlineUserList");
// 第一次使用前,需要初始化
if (onlineUserList == null) {
onlineUserList = new ArrayList();
application.setAttribute("onlineUserList", onlineUserList);
}
onlineUserList.add(this.username);
}
username已經(jīng)通過(guò)構(gòu)造方法傳遞給listener,在數(shù)據(jù)綁定時(shí),可以直接把它放入用戶(hù)列表。
與之對(duì)應(yīng)的valueUnbound()方法,代碼如下:
public void valueUnbound(HttpSessionBindingEvent event) {
HttpSession session = event.getSession();
ServletContext application = session.getServletContext();
// 從在線(xiàn)列表中刪除用戶(hù)名
List onlineUserList = (List) application.getAttribute("onlineUserList");
onlineUserList.remove(this.username);
System.out.println(this.username + "退出。");
}
這里可以直接使用listener的username操作在線(xiàn)列表,不必再去擔(dān)心session中是否存在username。
valueUnbound的觸發(fā)條件是以下三種情況:
-
執(zhí)行session.invalidate()時(shí)。
-
session超時(shí),自動(dòng)銷(xiāo)毀時(shí)。
-
執(zhí)行session.setAttribute("onlineUserListener", "其他對(duì)象");或session.removeAttribute("onlineUserListener");將listener從session中刪除時(shí)。
因此,只要不將listener從session中刪除,就可以監(jiān)聽(tīng)到session的銷(xiāo)毀。
(轉(zhuǎn)載...)
posted on 2008-10-16 12:27 找個(gè)美女做老婆 閱讀(3586) 評(píng)論(0) 編輯 收藏