这里说的关闭浏览器是,就是鼠标右键关闭,或者是点右上角的小叉子关闭。
以下是我在IE中 判断浏览器关闭或者刷新的方法
function unloadDestorySession(event) {
event = (event)?event:window.event;
if (event.clientX < 0 && event.clientY < 0 || event.altKey) {
alert("关闭");
}
} else {
alert("刷新");
}
}
在ie里一切正常,但是在firefox里面是没有办法执行的,我尝试了很多方法去解决这个问题,但是还是没办法。
希望有高人能解决这个问题,因为我在做一个实时聊天的应用,要监听实时在线的用户。关闭浏览器时,要销毁对应的session,要更新在线用户。
要求必须能在firefox下实现和上面程序一样的功能。
[b]问题补充:[/b]
首先感谢yourgame的回答,但是我想你误解我的意思了。
用户退出分为正常退出和非正常退出两种,我问这个问题就是为了处理非正常退出时的情况,比如:用户经常会不点退出按钮,而是直接点右键关闭,或者用Alt+F4,或者直接点右上角的叉叉关闭。
非正常关闭的用户,应该视为下线用户
我提问这个问题就是要在用户非正常关闭时,销毁相应的session,更新在线用户列表,并且给其他用户浏览器推入新的用户列表。
这个应经在IE下实现了,但是火狐不支持window.event事件,我实在处理不了
[b]问题补充:[/b]
yourgame 说:
首先,你这种做法就不正确。你不能通过onunload 来检测用户是否已经离线。
yourgame ,我说一下我是怎么做的在线用户。
我用了一个单例的List,用来存放在线用户,用户上线时,获得这个单例的实例,list.add(user),这里的User是一个pojo,代码如下:
package com.yunfei.pojo;
import java.io.Serializable;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
@SuppressWarnings("serial")
public class User implements HttpSessionBindingListener, Serializable {
private static final long serialVersionUID = 1549880235571202091L;
private int id;
private String username;
private String password;
private String sessionid;
private User u;
public User getU() {
return u;
}
public void setU(User u) {
this.u = u;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
private UserList userList = UserList.getInstance();
public void valueBound(HttpSessionBindingEvent e) {
System.out.println("==================================执行了valueBound");
System.out.println("addUser: " + u.getUsername());
userList.addUser(u);
System.out.println(userList.getList());
}
public void valueUnbound(HttpSessionBindingEvent e) {
System.out.println("==================================执行了valueUnBound");
System.out.println("RemoveUser: " + u.getUsername());
userList.removeUser(u);
System.out.println(userList.getList());
}
public String getSessionid() {
return sessionid;
}
public void setSessionid(String sessionid) {
this.sessionid = sessionid;
}
}
用户登陆时,新创建session,并且给User u,这个属性调用set方法,这样就会调用valueBound,单例userList就会增加一个新用户。然后把这个userList推入所有用户的浏览器中。退出时(正常退出就不说了),用户不点退出按钮,直接关闭浏览器,也视为退出,
用onunload就是为了在用户非正常退出时,触发一个事件,来从单例userList中remove这个用户,并且给其他用户浏览器推入新用户列表。但是刷新时,这些是不能被执行的。
这些功能在IE下都实现了,但是在火狐里由于window.event事件不兼容,我试验了不少方法,还是没有办法判断刷新,退出
[b]问题补充:[/b]
yourgame,你提供的思路倒是也可以考虑一下,但是服务器定期推消息怎么实现啊?我想了下好像没有类似的调用方法。可以提供一个例子吗?谢谢了。
ScriptSession这个对象只要刷新一下浏览器就会新增加一个,我后来解决了这个问题,就是用一个map来存放在线用户对应的ScriptSession,用户刷新和关闭浏览器的时候,也会更新或者删除对应的ScriptSession;
[b]问题补充:[/b]
还是比较期待有高人能解决这个问题,
function unloadDestorySession(event) {
event = (event)?event:window.event;
if (event.clientX < 0 && event.clientY < 0 || event.altKey) {
alert("关闭");
}
} else {
alert("刷新");
}
}
我那个示例中就有用到推技术呀。至于定期也很容易解决的。你去了解一下 java task
不过我不是让服务器定期推,我是只要有用户登录,就在登陆方法里面告诉服务器,现在可以推一下,看看在线情况。毕竟这个是暂用资源的 。
现在我们公司的那个系统都直接取消这个在线人数统计和在线聊天的了。因为没有实际用处。在线用户数量只对开发人员或者管理人员有一定的意义。一般都是放到后台管理里面。在业务系统里面直接不放这个
[quote]希望有高人能解决这个问题,因为我在做一个实时聊天的应用,要监听实时在线的用户。关闭浏览器时,要销毁对应的session,要更新在线用户。 [/quote]
首先,你这种做法就不正确。你不能通过onunload 来检测用户是否已经离线。
你可以采用服务器推技术(server push),来实现检测在线用户。关于推技术。你可以参考我博客里面的一片文章
[url]http://yourgame.iteye.com/blog/199079[/url]
我的建议是,也没有必要实时去检测在线用户是否还在线,你可以再用户登录的时候发送一个请求给服务器,让服务器通过推技术来检测当前有多少用户在线。这样效率要高一些。或则你用户点退出系统,也可以发送一个请求给服务器处理
你的意思我明白。
你可以看下我的示例中。在浏览器中有一个ScriptSession对象。每一个都是唯一的。当用户登录成功以后你把这个对象的一个id保存到服务器的单例list里面。如果要求实时性高 的话,你可以从服务器定期推一个消息。要求当前登陆成功的网页发送一个请求给服务器。来证明自己在线。否则将其及时移除list列表。和session销毁。我以前在我的系统里面是这样来实现的。这样就不用担心浏览器兼容的问题了