1. 程式人生 > >java 頁面線上訪問人數統計和線上登入人數統計

java 頁面線上訪問人數統計和線上登入人數統計

OnlineSessionListener監聽器(實現HttpSessionListener)介面來實現頁面線上訪問人數統計,當有使用者訪問到頁面就會建立一個session,此時會觸發public void sessionCreated(HttpSessionEvent se)方法,如果session失效,此時會觸發public void sessionDestroyed(HttpSessionEvent se)方法。在此方法裡我們用OnlineList進行線上訪問人數的統計

public class OnlineList {
private static final OnlineList onlineList = new OnlineList();
 private int maxSession;
 private int activeSession;
 
 
 private OnlineList()
 {
 //v = new Vector();
 }
 public static OnlineList getInstance()
 {
 return onlineList;
 }
 public void addSession(){
 activeSession++;
 if(activeSession>=maxSession){
 maxSession=activeSession;
 }
 }
 public void delSession(){
 if(activeSession > 0) 
 activeSession--; 
 }
 
 public int getActiveSession(){
 return activeSession;
}
public int getmaxSession(){
 return maxSession;
} 
}
public class OnlineSessionListener implements HttpSessionListener {
private OnlineList ol = OnlineList.getInstance();
public void sessionCreated(HttpSessionEvent arg0) {
 ol.addSession();
}
public void sessionDestroyed(HttpSessionEvent arg0) {
 ol.delSession();
}
}


用UserListener監聽器(實現HttpSessionAttributeListener介面)來實現線上登入人數統計,當有使用者新增到session中,監聽器就呼叫public void valueBound(HttpSessionBindingEvent event)方法。如果有使用者退出系統,監聽器就呼叫public void valueUnbound(HttpSessionBindingEvent event)方法。我們用UserList來統計使用者資訊

在UserList這個類的設計上,我們應用了單例(Singleton)設計模式,關於設計模式的知識,讀者可以參看相關的書籍。UserList是一個單例類,所謂單例類,是指一個類只有一個例項,而且自行例項化並向整個系統提供這個例項。單例類的一個最重要的特點是類的構造方法是私有的,從而避免了外部利用該類的構造方法直接建立多個例項。在程式碼的第8行,定義一個靜態的常量userList,它表示了UserList類的一個物件。在UserList類載入的時候,這個物件就產生了。第11~14行,宣告UserList類的構造方法為private,這是為了避免在外部使用UserList類的構造方法建立其物件。要注意的是,如果在類中不寫構造方法,那麼Java編譯器就會為這個類提供一個預設的不帶引數的公開的構造方法,這樣,在外部就可以通過類的構造方法建立物件了,那麼UserList也就不再是一個單例類了。既然UserList類的構造方法是私有的,那麼在外部就不能用new去構造物件,於是在程式碼的第16~19行,定義了一個靜態的方法getInstance(),在這個方法中,返回在類載入時建立的UserList類的物件。因為getInstance()方法本身是靜態的,所以可以直接通過類名來呼叫。
那麼為什麼要將UserList設計成單例類呢?這是因為UserList類的物件是用於儲存和獲取線上使用者的列表,而這個使用者列表對於所有的頁面來說都應該是同一個,所以將UserList類設計成單例類,這樣,所有的類訪問的就是同一個UserList物件了。
程式碼的第9行,定義了一個私有的Vector型別的變數,在UserList類的構造方法中,對Vector型別的變數v進行了初始化,用於存放String型別的物件。注意,在這個地方沒有使用ArrayList,是考慮到UserList物件可能會被多個執行緒同時訪問,因為ArrayList不是同步的,而Vector是同步的,所以採用Vector來儲存使用者列表。

import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
public class UserListener implements HttpSessionAttributeListener {
//使用者登入身份證
 private String USERNAME;
 private UserList u1 = UserList.getInstance(); 
 
 //判斷使用者是否存在
 public boolean IsExist(String sfz)throws Exception
 {
 try
 {
 
 return u1.IsExist(sfz);
 }
 catch(Exception ex)
 {
 ex.printStackTrace();
 return false;
 }
 }
 
public String getUSERNAME() {
 return USERNAME;
}
public void setUSERNAME(String username) {
 USERNAME = username;
}
public void attributeAdded(HttpSessionBindingEvent event) {
 try{
 if("USERNAME".equals(event.getName())){
 u1.addUser((String)event.getValue());
 }
 }catch(Exception e){
 e.printStackTrace();
 }
 
}
public void attributeRemoved(HttpSessionBindingEvent event) {
 try{
 if("USERNAME".equals(event.getName())){
 u1.RemoveUser((String)event.getValue());
 }
 }catch(Exception e){
 e.printStackTrace();
 }
 
}
public void attributeReplaced(HttpSessionBindingEvent arg0) {
 // TODO Auto-generated method stub
 
}
}
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;
public class UserList {
private static final UserList userList = new UserList();
 private Vector v = new Vector();
 private int maxUser;
 
 private UserList()
 {
 //v = new Vector();
 }
 public static UserList getInstance()
 {
 return userList;
 }
 //將使用者登陸身份證儲存到Vector中
 public void addUser(String sfz) throws Exception
 {
 try{
 if ( sfz != null&&!"".equals(sfz))
 {
 if ( v.indexOf(sfz) >= 0)//判斷是否已經存在
 return ; 
 //可能的操作
 //新增登入ID
 v.addElement(sfz);
 if(getUserCount()>maxUser){
 maxUser=getUserCount();
 }
 }
 }
 catch(Exception ex)
 {
 ex.printStackTrace(); 
 }
 finally{
 }
 }
 
 public boolean IsExist(String sfz)throws Exception
 {
 try{
 if ( v.indexOf(sfz) >= 0)
 return true; 
 return false;
 }
 catch(Exception ex)
 {
 ex.printStackTrace();
 return false;
 }
 }
 
 //刪除使用者登入ID
 public void RemoveUser(String sfz)throws Exception
 {
 try{
 if ( sfz != null&&!"".equals(sfz) )
 { 
 //修改資料庫
 //移除使用者登入ID
 v.removeElement(sfz);
 }
 }
 catch(Exception ex)
 { 
 ex.printStackTrace(); //寫日誌
 }
 finally{
 }
 }
 //返回Vector列舉
 public Enumeration getUserList()
 {
 return v.elements();
 }
 //返回迭代器
 public Iterator getUserListItera(){
 return v.iterator();
 }
 //返回線上人數
 public int getUserCount()
 {
 return v.size();
 }
 //返回線上人數峰值
 public int getMaxUser(){
 return maxUser;
 }
}
最後在web-xml裡 加入如下資訊
<listener>
 <listener-class>
 com.myxmu.listener.UserListener
 </listener-class>
</listener>


線上人數統計程式存在一些問題,如果使用者沒有退出登入而直接關閉了瀏覽器,那麼在伺服器端的Session中,這個使用者仍然是存在的,直到Session的超時值發生。所以線上人數統計只能做到在一個時間段內統計出大致的線上人數,而不能統計出精確的人數。為了提高統計的精確性,可以在客戶端設定指令碼,當瀏覽器關閉時,自動向伺服器傳送一個請求,伺服器收到這個請求後,使Session失效。不過,這也不能做到100%的精確,因為還存在著客戶端的瀏覽器異常終止,或者客戶機器崩潰的可能。