我要统计用户在线时间然后计费,现在如果正常退出已经可以统计了,但是如果非法退出导致session过期怎么处理,一旦session过期,session里存放的用户名和登陆时间就不存在了,怎么在监听器里统计呢?
我的监听器代码
package servlet;
import java.util.*;
import java.io.IOException;
import java.io.PrintWriter;import com.core.*;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSessionEvent;import Bean.book;
import Bean.user;public class userforlisten implements HttpSessionBindingListener{
private UserDB conn=null;
public void valueBound(HttpSessionBindingEvent event) {
    HttpSession session = event.getSession();
    ServletContext application = session.getServletContext();
    Date start=new Date();
    if(session.getAttribute("clock")==null) {session.setAttribute("clock",start);}
    // 第一次使用前,需要初始化
    System.out.println(session.getAttribute("username")+"reading");
} public void valueUnbound(HttpSessionBindingEvent event){
        HttpSession session = event.getSession();
String name=(String)session.getAttribute("username");
        System.out.print("session空");
        if(!(session.getAttribute("clock").equals(null))) {
     System.out.println("阅读退出");
        Date end=new Date();
        Date start=(Date)session.getAttribute("clock");
        session.removeAttribute("clock");
        long seconds=(end.getTime()-start.getTime())/1000;
        seconds=(int)(seconds+60)/60;
        System.out.print((end.getTime()-start.getTime())/1000);
        System.out.println("->>>"+seconds);
        book readbook=new book();
        user person=new user();
        person.SetUserCash(name, person.GetUserCash(name)-readbook.GetBookChargeFactor(Integer.parseInt((String)session.getAttribute("bookid")))*seconds);
        }
}
public userforlisten(){conn=new UserDB();}}

解决方案 »

  1.   

    刚刚想到两种方法:一种是在session过期前先回收计费并主动销毁session 另一种只能不把信息放到session,但是放到数据库好像也不行,有人能告诉我具体怎么做吗
      

  2.   

    放application里面吧,或者缓存应该都可以
      

  3.   

    非法退出?应该是传说中的直接关掉IE吧。。其实可以这么理解 在IE关闭的一瞬间触发onclose()事件 再去操作JS代码 <script>   
      function   window.onunload(){alert(这就是你要做的事,关闭网页之后做的!)}   
      function   window.onbeforeunload(){alert(这就是你要做的事,关闭网页之前做的!)}   
    </script>  
      

  4.   

    ???这么费事?难道我程序里写错了
    public class MySessionListener implements HttpSessionListener { public void sessionCreated(HttpSessionEvent se) {
    }
    public void sessionDestroyed(HttpSessionEvent se) {
    HttpSession session = se.getSession();
    if(session.getAttribute("loginUserId") == null) return;

    int userId = (Integer) session.getAttribute("loginUserId");
    String path = session.getServletContext().getRealPath("/varSmsDir");
    File file = new File(path +"/sessionvalid/" + userId + ".xls");
    if(file.exists()) {
    new RecursiveFileTemplate(new RecursiveFileCallBack(){
    public void handleFile(File file) {
    file.delete();
    //System.out.println("删除文件" + file.getAbsolutePath());
    }
    }).recursiveFile(new String[]{file.getAbsolutePath()});
    }
    }
    }
      

  5.   

    老问题了,http这种协议,注定了无法精确统计在线人数,永远有差异。当然,你非得用类似Flash实现的socket方式,也不是不可能,但对系统负载太高了。一句经典的案例:你知道中国有多少人吗? 我要求精确到纳秒级,精确到个位。
      

  6.   


    window.onunload这方法在IE中没问题,其他浏览器的话不敢保证
    所以用户的非法退出没有确实的方法可以捕获,还是等SESSION过期好了。
      

  7.   

    。。
    无语了。
    麻烦楼上诸位大神看清楚人家的需求。
    楼主问的问题是session过期后在他现在也的方法中得不到需要东西。不是你们说的那种需求,大家都知道http是什么东西。ps:楼主还可以在HttpSessionBindingListener的实现类里添加一个属性对象。在session绑定的时候
    session.setAttribute("bindinglis",new HttpSessionBindingListenerImpl(yourobject)).
    这样在valueUnbound的时候直接从HttpSessionBindingListenerImpl对象里取出来,当然如果这么写还得把HttpSessionBindingListenerImpl的默认构造方法给写上,。说了一推要是我理解错了,以后就不用发言了
      

  8.   


    当然向我上面那么写,要把你的valueBound内容写在用户登录的那段逻辑里
      

  9.   

    用户登录的时候记录它的登陆时间,退出的时候listener类记录它的退出时间,这样就可以统计他的在线时间/
      

  10.   


    valueUnbound可以捕获到SESSION失效的动作啊,session失效之前,可以通过valueUnbound来捕获session里存放的用户名和登陆时间的啊,不明白楼主为什么获取不了session内容。 ps,我的理解没有错吧?
      

  11.   

    你自己试一下就知道了。在valueUnbound里拿到的session已经是失效的了。虽然session不为null.
    实践一下。
      

  12.   


    哦? 是不是可以理解为,session在Timeout之前会先清除Attribute属性,而Attribute属性被删除时,会调用Unbound事件所以TimeOut时的执行顺序是:
    清除属性->Unbound事件调用->session销毁
      

  13.   

    查了下servlet文档Servlet 2.4以后的版本,TimeOut时监听器的执行顺序是:1. javax.servlet.http.HttpSessionListener接口的sessionDestroyed()方法
    2. javax.servlet.http.HttpSessionBindingListener接口的valueUnbound()方法
    3. javax.servlet.http.HttpSessionAttributeListener接口的attributeRemoved()方法所以楼主想要在TIMEOUT之前获取SESSION内容的话,最好用HttpSessionListener监听器