0、代码链接
链接:https://pan.baidu.com/s/1A3_xYyKTHbbZ6yJ16XXEqg
提取码:uss51、实现效果
谷歌浏览器访问:
同时打开IE浏览器访问:
关闭IE浏览器等待一分钟后刷新谷歌浏览器:
2、实现过程
代码思路:
1) 实现session和request的监听器,监听session的创建和销毁以及请求的到来;(P.S:注册监听器——Servlet3.0 监听器直接使用注解@webListener即可,不用在web.xml中布局)
2)在request监听器中维护一个当前完网站访问用户数组,当新请求到达时,获得(没有时会自动创建)用户sessionID,根据用户sessionID判断该用户是否已经在;如果该用户不存在则存入用户数组并将用户数据存入servletContext域。
3)在session监听器中维护一个当前网站访问人数的变量,当有新的session创建时,统计变量++并存于servletContext域、当有session被销毁,统计变量减一,并在获得用户数组,将该用户从用户数组中删除
思考:这里为什么没有将sessionID存入cookie或者重写URL,因为有监听器,监听器自动监听session的创建和销毁,不需要自己判断当前请求的sessionID来自哪个用户,逻辑上也用不到这个数据,这里这是实现session创建和销毁,不需要实现用户关闭浏览器再次打开依然可以找到用户对应在服务器端的session
- web.xml配置session销毁时间
拓展:监听器
概述:
常用来监听servletContext、httpSession、servletRequest等域对象的创建、销毁以及属性的变化等等,能够在这些事件动作前后进行一定的逻辑处理。
ServletContext对象的作用域在整个WEB应用程序,类似于Static属性;Session的作用域在一个会话,一个会话可以理解为一个从一个浏览器发出请求到服务器开始,一直到浏览器关闭(但通常我们可以设置会话的生命期,防止那些获得连接后却长时间没有再向服务器发出请求的情况),相当于类的成员变量;request的作用域仅在一次请求,即浏览器发送一次请求到服务器处理该请求并发回响应就结束了,相当于局部变量。
生命周期:
第一、servletContext 生命周期,是从系统启动至系统结束。系统启动时创建该对象,整个过程中这个对象是唯一的。 总结为四个字:“自始至终”。
第二、httpSession 生命周期,在一个session会话中有效,在一个session被创建直到失效的过程中都存在且有效,一个启动的服务中httpSession 对象能够有多个,即多线程。 总结为四个字:“回话期间”第三、servletRequest 生命周期,在一个request请求被创建和销毁的过程中有效,客户端每发起一次请求,即会创建一个新的servletRequest对象。 总结为资格字:“单次请求”。HttpsessionListener接口
Session创建事件,发生在每次一个新的session创建的时候;Session失效事件,发生在每次一个Session失效的时候。
这个接口也只包含两个方法,分别对应于Session的创建和失效:public void sessionCreated(HttpSessionEvent se); public void sessionDestroyed(HttpSessionEvent se);3、代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
package listener;import java.util.ArrayList;import javax.servlet.annotation.WebListener;import javax.servlet.http.HttpSessionEvent;import javax.servlet.http.HttpSessionListener;import model.User;import util.SessionUtil;/** * Application Lifecycle Listener implementation class MyHttpSessionListener * */@WebListenerpublic class MyHttpSessionListener implements HttpSessionListener { private int userCount; /** * Default constructor. */ public MyHttpSessionListener() { // TODO Auto-generated constructor stub } /** * @see HttpSessionListener#sessionCreated(HttpSessionEvent) */ public void sessionCreated(HttpSessionEvent arg0) { // TODO Auto-generated method stub userCount++; arg0.getSession().getServletContext().setAttribute("userCount", userCount); } /** * @see HttpSessionListener#sessionDestroyed(HttpSessionEvent) */ public void sessionDestroyed(HttpSessionEvent arg0) { // TODO Auto-generated method stub userCount--; arg0.getSession().getServletContext().setAttribute("userCount", userCount); ArrayListuserList = (ArrayList ) arg0.getSession().getServletContext().getAttribute("userList"); String sessionID = arg0.getSession().getId(); if(SessionUtil.getSessionById(userList, sessionID) != null){ userList.remove(SessionUtil.getSessionById(userList, sessionID)); } arg0.getSession().getServletContext().setAttribute("userList", userList); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
package listener;import java.util.ArrayList;import javax.servlet.ServletRequestEvent;import javax.servlet.ServletRequestListener;import javax.servlet.annotation.WebListener;import javax.servlet.http.HttpServletRequest;import model.User;import util.SessionUtil;/** * Application Lifecycle Listener implementation class MyRequestListener * */@WebListenerpublic class MyRequestListener implements ServletRequestListener { private ArrayListuserList; /** * Default constructor. */ public MyRequestListener() { // TODO Auto-generated constructor stub } /** * @see ServletRequestListener#requestDestroyed(ServletRequestEvent) */ public void requestDestroyed(ServletRequestEvent arg0) { // TODO Auto-generated method stub } /** * @see ServletRequestListener#requestInitialized(ServletRequestEvent) */ public void requestInitialized(ServletRequestEvent arg0) { // TODO Auto-generated method stub userList = (ArrayList ) arg0.getServletContext().getAttribute("userList"); if(userList == null){ userList = new ArrayList (); } HttpServletRequest httpServletRequest = (HttpServletRequest) arg0.getServletRequest(); //创建或获取session String sessionID = httpServletRequest.getSession().getId(); if(SessionUtil.getSessionById(userList, sessionID) == null){ User user = new User(); user.setSessionID(sessionID); userList.add(user); } arg0.getServletContext().setAttribute("userList", userList); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
package model;public class User { private String sessionID; private String userName; private String userPass; public String getSessionID() { return sessionID; } public String getUserName() { return userName; } public String getUserPass() { return userPass; } public void setSessionID(String sessionID) { this.sessionID = sessionID; } public void setUserName(String userName) { this.userName = userName; } public void setUserPass(String userPass) { this.userPass = userPass; }}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
package util;import java.util.ArrayList;import model.User;public class SessionUtil { public static User getSessionById(ArrayListuserList, String sessionID){ for(User user : userList){ if(user.getSessionID() == sessionID){ return user; } } return null; }}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>西南石油大学 - 计算机科学学院 计算机科学学院举办2019年寒假留校学生新春团拜会
在中华民族传统节日——春节即将到来之际,为让学院留校学生感受家的温暖,向他们传达学院的慰问和祝福。2019年2月1日上午9时30分,计算机科学学院在明理楼B306会议室隆重举行2019年寒假留…[详细信息]
4、相关资料
https://blog.csdn.net/zcw4237256/article/details/79140830 “当浏览器关闭时,Session就被销毁了?”