天天看點

頁面統計線上人數功能\浏覽器關閉原理

   關鍵技術支援:監聽器、unload(解除安裝)事件、load(加載)事件、session、application

一、理論知識:

   1.session在使用者進入伺服器時建立。

   2.application生命周期與伺服器同在。

   3.監聽器可以捕獲到session、application的建立與銷毀。

二、理論實作:

   1.監聽器捕獲到application建立時,設定線上人數為0,存儲在application中。

   2.捕獲到session建立時,application中的線上人數+1。

   3.捕獲到session銷毀時,application中的線上人數-1

三、主要技術難點:

   1.使用者直接關閉浏覽器\不經過登出這一步驟

   2.不存在頁面關閉事件與浏覽器關閉事件

解決方案

1.首先了解頁面重新整理原理與關閉頁面(浏覽器)原理重要部分

   頁面重新整理:觸發unload(解除安裝)\load(加載)事件

   關閉頁面:觸發unload(解除安裝)事件

2.由上述可知:關閉頁面不會觸發load事件

3.解決理論:

   <1>我們可以在window執行unload事件時,向伺服器發送生命中最後一個請求,請求伺服器清除目前的session,此處就可以讓監聽器捕獲到session銷毀。(存在重新整理問題—技術難點2)

解決重新整理問題:

   <2>由1可知,頁面重新整理時也會觸發該請求,為了避免重新整理也會删除目前的session,是以總結了上述的2。

   <3>事先配置一個load事件向伺服器請求。向伺服器發送生命中最後一個請求時,用新線程執行清除session,但在執行清除指令時,先讓該線程睡眠2s。在此同時,如果是重新整理頁面,會執行load事件中的請求,請求中斷線程執行清除session的指令。如果是退出頁面則,session會被正常清除,線上人數完成-1。

注意:

   如果是多使用者操作的情況下,要求保證方法、使用者、線程唯一性。

   線程必須保證每次頁面關閉請求時都是全新的。

   測試浏覽器:谷歌

代碼實作如下:

JavaScript

window.addEventListener('load',outWindow,false);
    window.addEventListener('unload',noOutWindow,false);
    function outWindow() {
        $.post('${top}/login?parameter=selectCheck&check=0');
    }
    function noOutWindow() {
        $.post('${top}/login?parameter=selectCheck&check=1');
    }
           

Java

private String str = "0";
private HttpSession session = null;
private Thread thread = null;
public void selectCheck(HttpServletRequest request) throws ServletException, IOException {
        //擷取參數
        String check = request.getParameter("check");
        if (check.trim().equals("1")){
            session = request.getSession();
            str=check.trim();
            thread=new Thread(){
                @Override
                public void run() {
                    try {
                        Thread.sleep(2000);
                        if (str.equals("1")){
                            //最終移除
                            session.invalidate();
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            thread.start();
        }else{
            str = "0";
            //中斷目前線程
            if (thread!=null){
                //原理:調用Java異常處理機制中斷線程
                thread.interrupt();
            }
        }
    }