描述:当用户关闭页面之后 达到指定得秒数,移除用户Session
思路:用户进入页面后一个ajax每间隔多少秒请求服务端发送心跳包,保存当前得时间戳,一旦用户关闭了页面,这个时间戳就不再改变,而服务端得定时器每间隔多久执行检查Session一旦发现这个session得时间戳超过了指定时间秒没有更新,则表示用户已经关闭了页面,则清除用户Session
页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
测试页面
<script>
setInterval(userActive, 20000); //如果用户打开了这个页面,每隔20秒页面发送一次心跳包存入当前时间戳,
function userActive(){
console.log("发送心跳包!");
var xmlReq;
if (window.XMLHttpRequest) {//如果windows支持XML请求对象
xmlReq = new XMLHttpRequest();
} else {
xmlReq = new ActiveObject('Microsoft.XMLHTTP');
}
xmlReq.onreadystatechange = function () {
if (xmlReq.readyState == 4 && xmlReq.status == 200) {
console.log(xmlReq.responseText);
}
}
xmlReq.open("GET", "checkUserActive", true);
xmlReq.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");//设置请求头信息
xmlReq.send("d="+new Date());
}
</script>
</body>
</html>
Controller
/**
* 接收请求得控制类
*/
@Controller
@RequestMapping("/test")
public class UserValidityDetection {
//当用户进入某个页面时 存入用户得某些Session 值
@RequestMapping("/")
public String pageSkip(HttpServletRequest request){
request.getSession().setAttribute("UserKey","this is test key");
//当用户进入页面时,需要保存一次当前活跃时间,避免用户进入后马上退出页面,无法监听用户是否在页面得活跃状态
checkUser(request);
//跳转页面时存入测试 session
return "test";
}
/**
* 查看用户session是否存在
* @param request
* @return
*/
@RequestMapping("/getUserKey")
@ResponseBody
public String getUserKey(HttpServletRequest request){
String UserKey = (String) request.getSession().getAttribute("UserKey");
//跳转页面时存入测试 session
return "{\"UserKey\":"+UserKey+"}";
}
/**
* 页面js每间隔多少秒请求一次,存入当前时间戳,标识用户打开浏览器中打开了当前页面
* @param request
*/
@RequestMapping("/checkUserActive")
@ResponseBody
public String checkUser( HttpServletRequest request){
//存入当前Session用户得活跃时间
request.getSession().setAttribute("userActiveTime",System.currentTimeMillis());
return "{\"code\":200,\"message\":\"The page remains active and successful!\"}";
}
}
服务端定时检查器
/**
* @author YuLF
* @version 1.0
* @date 2020/10/15 17:46
* 定时检查Session状态类
*/
@Component
@EnableScheduling
public class UserValidityDetectionChecker {
/**
* 用户离开页面多少秒 销毁用户Session,
* 因为定时检查是定时执行,存在一定得时间差,不过定时任务得执行间隔只要不是太长,那这个时间差就不会太大
* 比如说:当用户离开页面后,并不是只要达到了120秒就去移除Session,而是需要等待这个定时器再次执行
* 当用户离开页面120秒后销毁用户Session得某个Key
*/
private static final Integer USER_LEAVE_TIME = 120;
/**
* 定时检查任务执行得间隔时间 每1分钟执行一次定时任务检查
* 1.拿到所有用户Session进行遍历
* 2.判断每一个用户得session,userActiveTime(用户活跃时间戳),关闭当前页面是否超过了指定得秒数
* 3.关闭页面超过多少秒则移除用户session某个值
*/
@Scheduled(cron = "0 1/1 * * * ?")
public void checkUserPage(){
String needRemoveSession = "UserKey";//需要移除得Session
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + ":执行定时任务检查所有Session状态!");
Map<String,Object> sessionMap = SessionManager.getSessionMap();
Iterator<Map.Entry<String, Object>> iterator = sessionMap.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<String, Object> next = iterator.next();
HttpSession session = SessionManager.getSession(next.getKey());
//拿到用户在页面得最后一次活跃时间戳
String userActiveTime = session.getAttribute("userActiveTime")+"";
if(session.getAttribute(needRemoveSession) != null){
//用户关闭页面后大于指定得秒数,则移除session UserKey这个值
if(getDateDifference(userActiveTime) > USER_LEAVE_TIME){
//移除session中得某个session值 也可以直接移除用户Session
session.removeAttribute(needRemoveSession);
System.out.println(session.getId()+"离开页面:"+USER_LEAVE_TIME + "s,移除"+session.getId()+"得UserKey值");
}
}
}
}
/**
* 通过传入得毫秒时间戳,获取距离当前系统时间得秒数,来判断是否超过指定得秒数
* @param userActiveDateMs
* @return
*/
public static long getDateDifference(String userActiveDateMs){
return (System.currentTimeMillis() - (Long.parseLong(userActiveDateMs)))/1000;
}
}
Session管理器
/**
* @author YuLF
* @version 1.0
* @date 2020/10/15 17:52
* Session管理器,保存用户Session
*/
public class SessionManager {
private static Map<String,Object> map = new HashMap();
public static Map<String,Object> getSessionMap() {
return map;
}
public static synchronized void AddSession(HttpSession session) {
if (session != null) {
map.put(session.getId(), session);
}
}
public static synchronized void DelSession(HttpSession session) {
if (session != null) {
map.remove(session.getId());
}
}
public static synchronized HttpSession getSession(String session_id) {
if (session_id == null)
return null;
return (HttpSession) map.get(session_id);
}
}
Session监听器
/**
* @author YuLF
* @version 1.0
* @date 2020/10/15 17:51
* Session监听器
*/
public class SessionListener implements HttpSessionListener {
/**
* 当有新用户创建时,把他得Session添加到Session管理器
* @param httpSessionEvent /
*/
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
SessionManager.AddSession(httpSessionEvent.getSession());
}
/**
* 当有Session销毁时,从Session管理器移除
* @param httpSessionEvent /
*/
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
SessionManager.DelSession(session);
}
}
Web.xml
<!--会话管理-->
<listener>
<listener-class>com.fly.web.sessionlistener.SessionListener</listener-class>
</listener>