在最近的工作中,由于为系统修改bug,发现了这样一个问题 在我们现存的一个系统中存在以下一个需求: 当用户登录成功时,会记录用户的登陆时间,当用户登出这个系统时,记录登出系统的时间,该时间记录在日志中供用户进行查询。 这是一个很普通的用户需求,在这个系统中,登陆成功后,将记录用户登录时间,当用户使用系统提供的"退出系统"按钮退出时,将触发一个事件进行记录用户登出系统的时间以及清空该用户session的操作。问题就出现在这里,在一般情况下,一个b/s结构的系统,用户在退出系统时的习惯,大多数是直接关闭页面,而不是使用系统提供的"退出系统"操作,因此,对于退出时间的记录就无法实现了。 那么,如何准确的记录用户登出的时间呢?这个是我今天要在这里讨论的问题。 在web应用中,一般采用session来维护用户的信息,一个HttpSession的开始代表用户进入该系统,而该HttpSession的结束才说明该用户在该系统访问的结束。如果用户不是显式的调用HttpSession.invalidate()方法的话,一个HttpSession是不会被认为结束的。因此我认为应该通过监视用户登录后绑定的HttpSession的方法来监视用户的登入与登出。 这与一般的论坛记录当前在线用户的方法应该是相同的,如果不监视session,不考虑用户超时登出的情况,则在线人数可能会一直增加下去。 下面说明我用来解决该问题的方法: 实际上,方法很简单。我定一个类实现了HttpSessionBindingListener的接口,该接口提供了两个方法valueBound和valueUnbound,valueBound表示当session与预定义的对象绑定时调用,valueUnbound则为session与预定义的对象取消绑定的时候调用,当然如果session超时或者invalidate的时候都会被调用。定义了这个类后我们要做的就是将该监听器和session绑定到一起。使用HttpSession.setAttribute("BinderObject",new SessionBinder());这样的方法即可。在该方法执行后,程序将调用valueBound方法。而当执行HttpSession.invalidate()方法后或者session超时以后,程序将调用valueUnbound方法,这样就可以通过定义这两个方法的方法体实现记录登入和登出时间或者其他的操作了。 以下是部分相关代码:import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;public class SessionBinder implements HttpSessionBindingListener {
private String logId = ""; //将logId在加载session的时候进行记录,是因为当调用valueUnbound的时候无法在获取session中的信息 public void valueBound(HttpSessionBindingEvent event) {
logId = (String)event.getSession().getAttribute("logId");
System.out.println(logId+"Login successful");
} public void valueUnbound(HttpSessionBindingEvent event) {
System.out.println(logId+"Login out!");
if (logId != null) {
}}在登陆成功后绑定sessionrequest.getSession().setAttribute("logId", logId);request.getSession().setAttribute("BinderObject",new SessionBinder()); 登出时调用invaldate,取消session的绑定 request.getSession().invalidate();