统计在线用户人数,用户一登陆,在线人数加一,注销时在线人数减一,如果用户直接把浏览器关了或者非法退出?
我如何才能知道?并且能够在他非法退出时,对应的在线人数减一,而不是用户已经退出了,在线人数却没有改变?
用了监听器来做处理,在sessionDestroyed方法定义:public void sessionDestroyed(HttpSessionEvent event) {
HttpSession session = event.getSession();
ServletContext application = session.getServletContext(); // 取得登录的用户名
String username = (String) session.getAttribute("username");
List<String> users=(List) application.getAttribute("users");
users.remove(username);
System.out.println("非法退出,注销此用户:"+username); }
在调用session.invalidate();会自动执行此方法,但如果我直接关闭浏览器,这个方法不会被执行!求救高手了!
我如何才能知道?并且能够在他非法退出时,对应的在线人数减一,而不是用户已经退出了,在线人数却没有改变?
用了监听器来做处理,在sessionDestroyed方法定义:public void sessionDestroyed(HttpSessionEvent event) {
HttpSession session = event.getSession();
ServletContext application = session.getServletContext(); // 取得登录的用户名
String username = (String) session.getAttribute("username");
List<String> users=(List) application.getAttribute("users");
users.remove(username);
System.out.println("非法退出,注销此用户:"+username); }
在调用session.invalidate();会自动执行此方法,但如果我直接关闭浏览器,这个方法不会被执行!求救高手了!
页面卸载时再执行用户注销
楼主你现在做的已经可以了。session会超时的,超时了就自动销毁了。
如果我想链接到别的页面,结果session却已经把用户清除了,其实此时用户是应该还保存在session范围里的。
超时是可以解决,但如果我有一张用户表User,有个字段state,(0为不在线,可以登陆;1为在线,不能重复登陆),
我想登陆时,判断其state是否为0,为0才可以登陆,并且登陆成功后设置其状态为1,(防止重复登陆),用户退出时,再把
其状态设为0。如果按LS所说,直接断电或者非法退出时,其状态就不能修改了,还是1,下次再登陆时,岂不是无法登陆吗?
超过这个时间的话session就失效
设置时间的话,还是不灵活,有没有更好的办法?
再写一个单例的对象,内部保存已登录用户信息集合,同时开一个线程定时查询登录用户信息集合内当前系统时间-用户最后刷新时间是否超过默认的超时时间,如果超过则判定用户已退出。
最后在各个页面内要用Ajax技术及setTimeout函数定时向服务器发送请求,以刷新用户最后刷新时间。
要注意的是页面内的刷新间隔、服务端定时判定超时的线程的启动间隔及默认超时时间。
目前来说,楼主是不会得到满意答案,除非你能通过你的WEB服务器主动给每个登陆上来的客户端发信息。目前,你认为可能吗?
我之前做过,不过这个方法不怎么好,但能实现
//关闭浏览器的时候:
function window.onunload(){
window.location.href="/saizi/room.jsp";
}
//room.jsp的代码:这个网页可以自动关闭,不弹出提示. <% session.invalidate(); %>
<script type="text/javascript">
window.open("","_self");
window.close();
</script>
跟着就会马上调用session监听的sessionDestroyed()去减去一个用户,,
一、实现Session监听器
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;public class OnlineCounter implements HttpSessionListener {public synchronized void sessionCreated(HttpSessionEvent se){
String count = (String)se.getSession().getServletContext().getAttribute("count");
int c=0;
if(count !=null){
c = Integer.valueOf(count).intValue();
System.out.println("旧Count:"+c);
se.getSession().getServletContext().setAttribute("count",(c+1)+"");
}else{
System.out.println("新Count");
se.getSession().getServletContext().setAttribute("count",c+1+"");
}
System.out.println("建立session时 Count:"+c);
}public synchronized void sessionDestroyed(HttpSessionEvent se){
System.out.println("session失效时 ");
String count = (String)se.getSession().getServletContext().getAttribute("count");
int c=0 ;
if(count !=null){
c = Integer.valueOf(count).intValue();
if(c>=1){
System.out.println("sessionDestroyed:旧c-1:"+c);
se.getSession().getServletContext().setAttribute("count",(c-1)+"");
}
}else{
System.out.println("sessionDestroyed:旧新"+c);
se.getSession().getServletContext().setAttribute("count","1");
}
// session失效时
}
}
二、配置Session监听器 与Session存活时间<listener>
<listener-class>
com.longqiao.tools.servlet.OnlineCounter
</listener-class>
</listener>
<session-config>
<session-timeout>1</session-timeout> <!-- Session存活时间为1分钟 -->
</session-config>三、从前台提出网站在线人数...当前在线人数:${applicationScope.count}
如果用户在线时间超过1分钟,是不是用户就得自动下线了啊?
<% If Not Response.IsClientConnected Then ...%>
估计有点难!因为不是实时的,而且别人关闭时也不可能先和你打招呼的!
最多只能是在页面里加行代码,在正常关闭的时候给服务器发个消息,来注销session!
如果你非要解决的话也不是没有办法,但你要为此付出很大的代价.比如你可以用
服务器推技术,这时候你的程序已经跟c/s程序没有太大区别了,因为是实时连接
的,客户端掉了立即就可以察觉出来。但这样的话你的服务器所能处理的连接数就
很少了。用flash或applet和服务器端进行socket通信业可以实现服务器推,但这样做
有什么缺点,不用说大家也知道了。你自己权衡吧为了这点功能是否值得去做这些牺牲.
这有服务器推技术的一点资料,你可以参考下。做毕业设计的时候找到的,很久没弄了
http://www.ibm.com/developerworks/cn/web/wa-lo-comet/
1. 用户登录时,将 session 对象缓存到唯一实例对象中[这个对象中包含一个Map对象(key: loginName, value: session对象)];
2. 在sessionListener中清除正常退出或超时退出的用户session (同时从前面的Map对象中清除);
3. 相同登录名的用户登录时,首先缓存sessionId到另一个Map对象中(Key: sessionId, value: null),然后自动结束之前登录用户的session(就是让session立即过期),并同时从前面的Map对象中清除(使用loginName清除);
4. 使用一个Filter程序,接收其请求中的sessionId(即:request.getRequestedSessionId();),判断该sessionId是否在Map对象中,如果是,则直接跳转到错误页面并提示“您的账号被重复登录,因此您已被强制退出,请重新登录。”这样,后者将前者踢出,就不存在后来者不能登录的情况了;之前登录的用户被踢出后,再次请求时,会自动显示被踢出的提示信息。另:加上一个配置选项,就可实现是否允许重复登录的功能。
1. 用户登录时,将 session 对象缓存到唯一实例对象中[这个对象中包含一个Map对象(key: loginName, value: session对象)];
2. 在sessionListener中清除正常退出或超时退出的用户session (同时从前面的Map对象中清除);
3. 相同登录名的用户登录时,首先缓存sessionId到另一个Map对象中(Key: sessionId, value: null),然后自动结束之前登录用户的session(就是让session立即过期),并同时从前面的Map对象中清除(使用loginName清除);
4. 使用一个Filter程序,接收其请求中的sessionId(即:request.getRequestedSessionId();),判断该sessionId是否在Map对象中,如果是,则直接跳转到错误页面并提示“您的账号被重复登录,因此您已被强制退出,请重新登录。”,并从该Map对象中清除该sessionId。这样,后者将前者踢出,就不存在后来者不能登录的情况了;之前登录的用户被踢出后,再次请求时,会自动显示被踢出的提示信息(仅可提示一次)。 另:加上一个配置选项,就可实现是否允许重复登录的功能。
function window.onunload()
{
if(event.clientX>document.body.clientWidth&&event.clientY<0||event.altKey||event.ctrlKey)
{
var rightId = document.forms[0].elements("rightId").value;
self.location.href="./AAA.do?actionMethod=doDestroy&rightId="+rightId;
window.close();
}
} LZ 用这个方法试试
function window.onunload()
{
//这个IF用于判断是刷新还是关闭,如果是关闭就进入下面代码href去ACTION中请求销毁session对象
if(event.clientX>document.body.clientWidth&&event.clientY <0||event.altKey||event.ctrlKey)
{
var rightId = document.forms[0].elements("rightId").value;
self.location.href="./AAA.do?actionMethod=doDestroy&rightId="+rightId;
window.close();
}
} event.clientX鼠标的x坐标
document.body.clientWidth 视窗宽度
event.clientY鼠标的y坐标
event.altKey alt键 event.ctrlKey 雷同回复当前鼠标x坐标值大于文档宽度并且鼠标y坐标值小于0或者alt键被按下或者ctrl键被按下
public ActionForward doDestroy(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
{
if(request.getSession().getAttribute("XXXVO")!=null)
{
request.getSession().removeAttribute("XXXVO");
}
return null;
}
当然也有问题,比如浏览器的问题,突然断电等问题,我是没去试过。只是给你个建议吧 呵呵
然后写一个js,用ajax在后台,定时(每2秒)刷一个心跳页面用来维持session的时效;这样用户不管什么原因,只要那个页面关掉了,js脚本就不会被执行,没有心跳,10秒后自然就下线了这样可以解决用户在这个页面但是很久不动作的情况但是有对于管服务器还是客户端开销增加的弊端
不是不行,是有没有必要的问题,因为你要把请求-响应 模式改变成 实时模式,开销肯定很大;
function onLine(){
createXMLHttpRequest();
var url = "servlet/innerCommManageServlet.do?action=onLine&userName=${employee.userName}";
xmlHttp.open("get",url,true);
xmlHttp.onreadystatechange = onMessage;
xmlHttp.send(null);
}
function onMessage(){
if(xmlHttp.readyState == 4){
if(xmlHttp.status == 200){
}
}
}
window.onload =function(){
setInterval("onLine()",5000);
} 我以前好像做过这样的项目
应该是判断的问题:
if(event.clientX>document.body.clientWidth&&event.clientY <0||event.altKey||event.ctrlKey)
这个判断用在IE上可以,如果要兼容其他浏览器该如何写?