1. 程式人生 > >springboot 用監聽器統計線上人數,小案例

springboot 用監聽器統計線上人數,小案例

本文在springboot 的專案,用HttpSessionListener 監聽器(監聽器的其中一種) 統計線上人數,實質是統計session 的數量。

思路很簡單,但是有個細節沒處理好,讓我除錯了大半天,才把bug搞好。

先寫個HttpSessionListener 監聽器。count  是session的數量(人數),session 建立的時候,會觸發監聽器的sessionCreated 方法,session銷燬的時候,會觸發監聽器的sessionDestroyed 方法。 在監聽器中計算完人數count,把他放進servletContext(可以理解為一個倉庫,任意請求可以儲存和獲取裡面的屬性)。

注意監聽器加上@WebListener,這樣就不用配置。

@WebListener
public class OnLineCount implements HttpSessionListener {
    public int count=0;//記錄session的數量
    //監聽session的建立,synchronized 防併發bug
    public synchronized void sessionCreated(HttpSessionEvent arg0) {
        System.out.println("【HttpSessionListener監聽器】count++  增加");
        count++;
        arg0.getSession().getServletContext().setAttribute("count", count);

    }
    @Override
    public synchronized void sessionDestroyed(HttpSessionEvent arg0) {//監聽session的撤銷
        System.out.println("【HttpSessionListener監聽器】count--  減少");
        count--;
        arg0.getSession().getServletContext().setAttribute("count", count);
    }
}


接著寫一個查詢session 數量的controller,我開始的時候是像下面這樣寫的,是錯誤的!

從servletContext 中取出count ,把count返回前端。

    @RequestMapping("/count")
    @ResponseBody
    public String count(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse){
        Object count=httpServletRequest.getServletContext().getAttribute("count");
        return "count : "+count;
    }
這樣是錯誤的,測試你會發現,頁面看到count  是null ,因為沒有建立session,沒有觸發監聽器的統計方法。於是改一下:
@Controller
public class IndexController {
    @RequestMapping("/count")
    @ResponseBody
    public String count(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse){
        HttpSession session = httpServletRequest.getSession();
        Object count=session.getServletContext().getAttribute("count");
        return "count : "+count;
    }
}

HttpSession session = httpServletRequest.getSession();  作用:該使用者如果沒有sesision則建立session ,有則取得session不建立。

改成這樣測試,看起來是對的,但是有個問題。一個瀏覽器對應一個session,你開啟2個瀏覽器,看到count是2 ,是對的。但是你關了一個瀏覽器,再開啟,應該是2不變才對,但是變成3 了,原因是session銷燬的方法沒有執行,重新開啟時,伺服器找不到使用者原來的session ,重新建立了一個session,於是有3個session了,但是瀏覽器只有2個,也就是模擬應該是隻有2個人在線上。

有2個方法可以解決這個問題,一個是在關閉網頁的時候,前端去呼叫一個方法把session銷燬。另一個更好的方法是,讓伺服器記得原來那個session,即把原來的sessionId 記錄在瀏覽器,下次開啟時,把這個sessionId傳送過去,這樣伺服器就不會重新建立。

程式碼修改如下:

@Controller
public class IndexController {
    @RequestMapping("/count")
    @ResponseBody
    public String number(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse){
        try{  //把sessionId記錄在瀏覽器
            Cookie c = new Cookie("JSESSIONID", URLEncoder.encode(httpServletRequest.getSession().getId(), "utf-8"));
            c.setPath("/");
            //先設定cookie有效期為2天,不用擔心,session不會儲存2天
            c.setMaxAge( 48*60 * 60);
            httpServletResponse.addCookie(c);
        }catch (Exception e){
            e.printStackTrace();
        }

        HttpSession session = httpServletRequest.getSession();
        Object count=session.getServletContext().getAttribute("count");
        return "count : "+count;
    }
}
測試達到效果。