本文在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不創建。
有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;
}
}
測試達到效果。