實現(xiàn)思路
通過監(jiān)聽ServletContext,ServletRequest,HttpSession來統(tǒng)計頁面的訪問人數叫挟。根據Session的創(chuàng)建方式,在切換另一個游覽器時創(chuàng)建了新的Session,所以用了作用域更高的ServletContext來監(jiān)聽.在ServletContext中存放以用戶ip為Key的Map弄跌。Value為Session的集合莺琳。在用戶訪問時把產生的ip和Session傳入map里,Session銷毀時,移出map中相關的數據被廓。具體步驟如下:
1.創(chuàng)建ServletContext監(jiān)聽
@Component
public class ServletContextListener implements javax.servlet.ServletContextListener {
private Map<String, List<HttpSession>> userMap = new HashMap<>();
@Override
public void contextInitialized(ServletContextEvent sce) {
sce.getServletContext().setAttribute("userMap",userMap);
}
}
在監(jiān)聽中創(chuàng)建訪問人數的mao集合,數據存入ServletContext中。
2.創(chuàng)建HttpSeesion監(jiān)聽
@Component
public class HttpSessionListener implements javax.servlet.http.HttpSessionListener {
/**
* session失效后執(zhí)行
*/
@Override
public void sessionDestroyed(HttpSessionEvent se) {
//獲取session
HttpSession session = se.getSession();
String ip = (String) session.getAttribute("ip");
//獲取servletContext
ServletContext servletContext = session.getServletContext();
//獲取userMap
Map<String, List<HttpSession>> userMap = (Map<String, List<HttpSession>>) servletContext.getAttribute("userMap");
List<HttpSession> sessions = userMap.get(ip);
//移除session
sessions.remove(session);
//如果sessionList的長度為0,說明沒有以這個ip訪問的用戶已經下線,從user,map中移出ip蛉鹿。
if(sessions.size()==0){
userMap.remove(ip);
}else{
userMap.put(ip, sessions);
}
servletContext.setAttribute("userMap", userMap);
}
}
//session銷毀的監(jiān)聽,在session銷毀時,先從sessionList中移除Session取劫,如果list長度為0則說明用戶以及下線(基于不同的游覽器可以產生的session),從用戶map中刪除。
3.ServletContest監(jiān)聽
@Component
public class RequestContextListener implements ServletRequestListener {
@Override
public void requestInitialized(ServletRequestEvent sre) {
ServletRequest servletRequest = sre.getServletRequest();
//獲取ip,存入ServletContext
String ip = servletRequest.getRemoteAddr();
HttpServletRequest request = (HttpServletRequest) servletRequest;
//獲取session
HttpSession session = request.getSession();
session.setAttribute("ip",ip);
//獲取map集合
ServletContext servletContext = sre.getServletContext();
Map<String, List<HttpSession>> userMap = (Map<String, List<HttpSession>>) servletContext.getAttribute("userMap");
//獲取sessionList
List<HttpSession> sessionList=userMap.containsKey(ip) ? userMap.get(ip) : new ArrayList<>();
if(!sessionList.contains(session)){
sessionList.add(session);
}
userMap.put(ip, sessionList);
//存入userMap
servletContext.setAttribute("userMap",userMap);
}
}
在有請求訪問站點時,獲取session,通過request獲取用戶路由地址忌卤。把地址存入session中.判斷Map中是否存在相同的ip,如果沒有創(chuàng)建lsessionList,把ip和lsessionLst存入userMap中跑揉。如果存在相同的ip,則獲取sessionList,把session存入.最后在把數據保存在userMap中。
測試
設置session的過時時間為5秒埠巨。
index.html
<h1>
Hello World
</h1>
當前在線人數:
<span th:text="${application.userMap}" ></span>
<br>
<span th:text="${application.userMap.size()}" ></span>
以localhost:8080訪問
兩個游覽器以localhost:8080訪問
一個游覽器以localhost:8080訪問一個以127.0.0.1:8080訪問
等session過時再次訪問