java web开发一个帐号同一时间只能一个人登录
可采用如下解决方案:
1 .当用户第一次登录时,把用户添加到一个ArrayList中,再次登录时查看ArrayList中有没有该用户,如果ArrayList中已经存在该用户,则阻止其登录。(说明,为保证该操作在每一次登录时都能执行,最好写在一个filter或listener中),代码参考如下:
public static List loginInfoList=Collections.synchronizedList(new ArrayList()); //保存所有登录帐户(要作为一个静态成员变量保存) boolean accountLogined=false; // 账户是否已经登录if(HomeController.loginInfoList.isEmpty()){HomeController.loginInfoList.add(loginInfo); // loginInfo:当前登录帐户}}else{ for(int i=0;i<HomeController.loginInfoList.size();i++){LoginInfo tempInfo=HomeController.loginInfoList.get(i); if(tempInfo.getUserId().equals(MisUtils.getSessionUser(request).getId())){accountLogined=true;// 当前账户已在使用break; } } if(!accountLogined){ // 列表中不存在该账户HomeController.loginInfoList.add(loginInfo); } } if(accountLogined){ throw new MisException("当前账户正在使用,不能重复登录"); }
?
?
?
2、当用户退出时,需要从该ArrayList中删除该用户,这又分为三种情况
① 使用注销按钮正常退出
② 点击浏览器关闭按钮或者用Alt+F4退出,可以用javascript捕捉该页面关闭事件,
执行一段java方法删除ArrayList中的用户
③ 非正常退出,比如客户端系统崩溃或突然死机,可以采用隔一段时间session没活动就删除该session所对应的用户来解决,这样用户需要等待一段时间之后就可以正常登录。
①③ 可采用相同的核心代码,只不过③须放在一个sessionListener中,参考代码如下:
?
?
Iterator<LoginInfo> it=HomeController.loginInfoList.iterator();while(it.hasNext()){ LoginInfo tempInfo=it.next(); if(MisUtils.getSessionUser(req).getId().equals(tempInfo.getUserId())){ //MisUtils.getSessionUser(req).getId()为当前登录用户的id it.remove(); } }
?
?
?说明:对于在遍历list的同时进行删除操作,最好通过Iterator,否则如果一次要删除多个元素时,通过loginInfoList.remove(i)可能出现与期望值不一样的结果。
对于② 浏览器关闭时,可在前台使用 window.onbeforeunload事件进行捕捉,并使用ajax从列表中删除用户,参考如下:
//窗口关闭时触发 window.onbeforeunload=function(){ if(event.clientX>document.body.clientWidth && event.clientY<0||event.altKey||window.event.ctrlKey){ $.get("destroyCurrentUser.htm"); //jquery中简单的ajax } }
?
?其中destroyCurrentUser.htm中的核心代码与前面类似。
当然这种解决方案还存在许多问题,比如① 客户端死机情况下用户并不会从列表中删除,致使下次再无法登录;②当使用多标签浏览器时,关闭浏览器,window.onbeforeunload事件通常不会触发,导致登录用户也不会从列表中删除。所以最好是建一个可以无限次登录的super账户,并能查看登录用户列表及强制注销登录用户。如图所示:
?
?