用HttpSessionListener與HttpSessionBindingListener實現在線人數統計
作者1:try出愛的異常
作者2:長安散人
下午比較閑(其實今天都很閑),想了一下在線人數統計方面的實現,上網找了下這方面的知識,最初我的想法是,管理session,如果session銷毀了就減少,如果登陸用戶了就新增一個,但是如果是用戶非法退出,如:未註銷,關閉瀏覽器等,這個用戶的session是管理不到的,最後決定用HttpSessionListener接口或HttpSessionBindingListener接口來實現,通過監聽session的新建和銷毀來控制,詳細如下。
先添加登陸的頁面index.jsp
<%@ page contentType="text/html;charset=utf-8"%> <html> <head> <title>test</title> </head> <body> <form action="login.jsp" method="post"> 用戶名:<input type="text" name="username" /> <br /> <input type="submit" value="登錄" /> </form> </body> </html>
點擊登陸後跳轉的login.jsp(為了方便,用jsp做servlet,同學們用的時候記得改過來)
<%@ page contentType="text/html;charset=utf-8"%> <%@ page import="java.util.*"%> <% request.setCharacterEncoding("UTF-8"); // 取得登錄的用戶名 String username = request.getParameter("username"); // 把用戶名保存進session session.setAttribute("username", username); // 把用戶名放入在線列表 List onlineUserList = (List) application.getAttribute("onlineUserList"); // 第一次使用前,需要初始化 if (onlineUserList == null) { onlineUserList = new ArrayList(); application.setAttribute("onlineUserList", onlineUserList); } onlineUserList.add(username); // 成功 response.sendRedirect("result.jsp"); %>
登陸成功跳轉到顯示頁面result.jsp
<%@ page contentType="text/html;charset=utf-8"%> <%@ page isELIgnored="false"%> <%@page import="java.util.List"%> <h3>您好:${username} [<a href="logout.jsp">註銷</a>]</h3> 當前在線用戶: <table> <% List onlineUserList = (List) application.getAttribute("onlineUserList"); for (int i = 0; i < onlineUserList.size(); i++) { String onlineUsername = (String) onlineUserList.get(i); %> <tr> <td><%=onlineUsername%></td> </tr> <% } %> </table>
點擊註銷頁面logout.jsp頁面
<%@ page contentType="text/html;charset=utf-8"%> <%@ page import="java.util.*"%> <% // 取得登錄的用戶名 String username = (String) session.getAttribute("username"); // 銷毀session session.invalidate(); // 從在線列表中刪除用戶名 List onlineUserList = (List) application.getAttribute("onlineUserList"); onlineUserList.remove(username); // 成功 response.sendRedirect("index.jsp"); %>
OK,登陸、查看、註銷頁面都有了,下面開始新建監聽器
1、HttpSessionListener
添加類OnlineUserListener,繼承HttpSessionListener,HttpSessionListener中有兩個方法sessionCreated(HttpSessionEvent event)與sessionDestroyed(HttpSessionEvent event),前者是監聽session的新建,後者是監聽session的銷毀。
OnlineUserListener代碼如下:
package com.test; import java.util.List; import javax.servlet.ServletContext; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; /** * @author 版本 */ public class OnlineUserListener implements HttpSessionListener { public void sessionCreated(HttpSessionEvent event) { System.out.println("新建session:"+event.getSession().getId()); } public void sessionDestroyed(HttpSessionEvent event) { HttpSession session = event.getSession(); ServletContext application = session.getServletContext(); // 取得登錄的用戶名 String username = (String) session.getAttribute("username"); // 從在線列表中刪除用戶名 List onlineUserList = (List) application.getAttribute("onlineUserList"); onlineUserList.remove(username); System.out.println(username+"已經退出!"); } }
web.xml配置:
<listener> <listener-class>com.test.OnlineUserListener</listener-class> </listener>
一旦監聽器發現調用了sessionDestoryed方法就會把其用戶從在線人數中delete,在下面兩種情況下會發生sessionDestoryed事件
a.執行session.invalidate()方法時
logout.jsp中調用了 session.invalidate()方法
b.session會話超時
session的默認超時事件是30分鐘,30分鐘後自動銷毀session
2、HttpSessionBindingListener
HttpSessionBindingListener雖然叫做監聽器,但使用方法與HttpSessionListener完全不同。我們實際看一下它是如何使用的。
新建類OnlineUserBindingListener,實現HttpSessionBindingListener接口,構造方法傳入username參數,HttpSessionBindingListener內有兩個方法valueBound(HttpSessionBindingEvent event)和valueUnbound(HttpSessionBindingEvent event),前者為數據綁定,後者為取消綁定
所謂對session進行數據綁定,就是調用session.setAttribute()把HttpSessionBindingListener保存進session中。
在login.jsp中做這一步:
<%@page import="com.test.OnlineUserBindingListener"%> <%@ page contentType="text/html;charset=utf-8"%> <%@ page import="java.util.*"%> <% request.setCharacterEncoding("UTF-8"); // 取得登錄的用戶名 String username = request.getParameter("username"); // 把用戶名放入在線列表 session.setAttribute("onlineUserBindingListener", new OnlineUserBindingListener(username)); // 成功 response.sendRedirect("result.jsp"); %>
這就是HttpSessionBindingListener和HttpSessionListener之間的最大區別:HttpSessionListener只需要設置到web.xml中就可以監聽整個應用中的所有session。HttpSessionBindingListener必須實例化後放入某一個session中,才可以進行監聽。
從監聽範圍上比較,HttpSessionListener設置一次就可以監聽所有session,HttpSessionBindingListener通常都是一對一的。
正是這種區別成就了HttpSessionBindingListener的優勢,我們可以讓每個listener對應一個username,這樣就不需要每次再去session中讀取username,進一步可以將所有操作在線列表的代碼都移入listener,更容易維護。
HttpSessionBindingListener代碼如下:
package com.test; import java.util.ArrayList; import java.util.List; import javax.servlet.ServletContext; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionBindingListener; public class OnlineUserBindingListener implements HttpSessionBindingListener { String username; public OnlineUserBindingListener(String username){ this.username=username; } public void valueBound(HttpSessionBindingEvent event) { HttpSession session = event.getSession(); ServletContext application = session.getServletContext(); // 把用戶名放入在線列表 List onlineUserList = (List) application.getAttribute("onlineUserList"); // 第一次使用前,需要初始化 if (onlineUserList == null) { onlineUserList = new ArrayList(); application.setAttribute("onlineUserList", onlineUserList); } onlineUserList.add(this.username); } public void valueUnbound(HttpSessionBindingEvent event) { HttpSession session = event.getSession(); ServletContext application = session.getServletContext(); // 從在線列表中刪除用戶名 List onlineUserList = (List) application.getAttribute("onlineUserList"); onlineUserList.remove(this.username); System.out.println(this.username + "退出。"); } }
這裏可以直接使用listener的username操作在線列表,不必再去擔心session中是否存在username。
valueUnbound的觸發條件是以下三種情況:
a.執行session.invalidate()時。
b.session超時,自動銷毀時。
c.執行session.setAttribute("onlineUserListener", "其他對象");或session.removeAttribute("onlineUserListener");將listener從session中刪除時。
因此,只要不將listener從session中刪除,就可以監聽到session的銷毀。
附註: Java設置session超時(失效)的三種方式
1. 在web容器中設置(此處以tomcat為例)
在tomcat-5.0.28\conf\web.xml中設置,以下是tomcat 5.0中的默認配置:
- <!-- ==================== Default Session Configuration ================= -->
- <!-- You can set the default session timeout (in minutes) for all newly -->
- <!-- created sessions by modifying the value below. -->
- <session-config>
- <session-timeout>30</session-timeout>
- </session-config>
Tomcat默認session超時時間為30分鐘,可以根據需要修改,負數或0為不限制session失效時間。
2. 在工程的web.xml中設置
- <!-- 時間單位為分鐘 -->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
3. 通過Java代碼設置
session.setMaxInactiveInterval(30*60);//以秒為單位
三種方式優先級:1 < 2 <3
用HttpSessionListener與HttpSessionBindingListener實現在線人數統計