关键技术支持:监听器、unload(卸载)事件、load(加载)事件、session、application
一、理论知识:
1.session在用户进入服务器时创建。
2.application生命周期与服务器同在。
3.监听器可以捕获到session、application的创建与销毁。
二、理论实现:
1.监听器捕获到application创建时,设置在线人数为0,存储在application中。
2.捕获到session创建时,application中的在线人数+1。
3.捕获到session销毁时,application中的在线人数-1
三、主要技术难点:
1.用户直接关闭浏览器\不经过退出登录这一步骤
2.不存在页面关闭事件与浏览器关闭事件
解决方案
1.首先理解页面刷新原理与关闭页面(浏览器)原理重要部分
页面刷新:触发unload(卸载)\load(加载)事件
关闭页面:触发unload(卸载)事件
2.由上述可知:关闭页面不会触发load事件
3.解决理论:
<1>我们可以在window执行unload事件时,向服务器发送生命中最后一个请求,请求服务器清除当前的session,此处就可以让监听器捕获到session销毁。(存在刷新问题—技术难点2)
解决刷新问题:
<2>由1可知,页面刷新时也会触发该请求,为了避免刷新也会删除当前的session,所以总结了上述的2。
<3>事先配置一个load事件向服务器请求。向服务器发送生命中最后一个请求时,用新线程执行清除session,但在执行清除命令时,先让该线程睡眠2s。在此同时,如果是刷新页面,会执行load事件中的请求,请求中断线程执行清除session的指令。如果是退出页面则,session会被正常清除,在线人数完成-1。
注意:
如果是多用户操作的情况下,要求保证方法、用户、线程唯一性。
线程必须保证每次页面关闭请求时都是全新的。
测试浏览器:谷歌
代码实现如下:
JavaScript
window.addEventListener('load',outWindow,false);
window.addEventListener('unload',noOutWindow,false);
function outWindow() {
$.post('${top}/login?parameter=selectCheck&check=0');
}
function noOutWindow() {
$.post('${top}/login?parameter=selectCheck&check=1');
}
Java
private String str = "0";
private HttpSession session = null;
private Thread thread = null;
public void selectCheck(HttpServletRequest request) throws ServletException, IOException {
//获取参数
String check = request.getParameter("check");
if (check.trim().equals("1")){
session = request.getSession();
str=check.trim();
thread=new Thread(){
@Override
public void run() {
try {
Thread.sleep(2000);
if (str.equals("1")){
//最终移除
session.invalidate();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
}else{
str = "0";
//中断当前线程
if (thread!=null){
//原理:调用Java异常处理机制中断线程
thread.interrupt();
}
}
}