由于页面的Ajax的定时请求服务器,导致了当前用户session永远不会超时。所以我决定用Filter过滤器加Timer的方法来解决这个问题,我在代码里用户每一次访问会新建的Timer,清除上一个Timer,但是发现我怎样做都不会清除上一个Timer,他到时间还是会执行!请问这个有什么错误,应该怎么解决啊?或者可以用别的什么方案来解决不超时的问题!非常感谢,代码如下!import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;public class SessionTimeOutFilter implements Filter {
private int num = -1;
private String filterUrl;
private String sessionKey;
private static Map<String,Timer> map = new HashMap<String,Timer>(); public void init(FilterConfig filterConfig) throws ServletException {
sessionKey = filterConfig.getInitParameter("SessionKey");
filterUrl = filterConfig.getInitParameter("filterUrl");
}

public void destroy() {} public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
if(num<0){
num = request.getSession().getMaxInactiveInterval();
}
String url = request.getServletPath();
if(url!=null && !"".equals(url) && !filterUrl.equals(url)){
HttpSession session = request.getSession();
Timer timer = map.get(session.getId());
if(timer!=null){
map.remove(session.getId());
timer.cancel();
timer = null;
}
timer = new Timer();
timer.schedule(new SessionTimeOut(session,sessionKey), num * 1000);
map.put(session.getId(), timer);
}
chain.doFilter(req, resp);
} class SessionTimeOut extends TimerTask {
private HttpSession session;
private String sessionKey;

public SessionTimeOut(HttpSession session, String sessionKey){
this.session = session;
this.sessionKey = sessionKey;
}

public void run() {
if(session!=null){
session.removeAttribute(sessionKey);
//this.session.invalidate();
}
}
}
}

解决方案 »

  1.   

    要解决永不超时的问题可以不需要Timer的Ajax定时访问的应该只是同一个页面吧,你增加一个Filter过滤/*,如果请求的不是那个定时访问页面,则在session.setAttribute("_LAST_ACCESS_TIME", new Date());如果访问的是定时页面,则判断request.getSession(false)是否为null,如果为空则表示还没有会话,直接返回;如果不为空,则判断getAttribute("_LAST_ACCESS_TIME")的date比当前时间早多少分钟,如果超过设定,则调用session.invalidate();
    你可以先不要调用request.getSession(),防止当会话超时后再次访问时会创建一个空白的Session
      

  2.   

    你这个timer的方式没法给你具体测试了,但是我知道jsp可以禁用当前页的session。好像是在page标签内设置session="false",不知道这个方法是否可行,将你ajax请求的url对应的jsp或者sevlet设置为不使用session的页面,不知道这样是否能解决这个问题。
    还有,你的这句:if(url!=null && !"".equals(url) && !filterUrl.equals(url))里的语句确实被执行了吗?
      

  3.   

    if(url!=null && !"".equals(url) && !filterUrl.equals(url))  这句肯定被执行了,跟踪过!
    问题是我的Ajax请求是请求的后台,是要去读数据库的,相当于去监视数据库是否有新数据。那上面的方法还有用么?
      

  4.   

    禁用session以后就得不到身份信息了。
    何不直接把Timer放在session里?
    另外:过滤器是可以设定过滤哪些url的。你可以通过这个来指定而不是通过过滤器内部来分析,因为这是可以灵活配置的。
      

  5.   

    放在session里,也不行,以前试过~~~~~
      

  6.   

    放在Session当然是可行啊,只是需要你自己判断是否应该手工调用invalidate而已
    你以前有什么问题?
      

  7.   


    我放入session中,然后取出来然后清除Timer,重新放入一个新的Timer,问题就是前一个Timer根本不会清除,到时间他还是会执行!!!
    在page标签内设置session="false"禁用当前页的session,要是我这个页面是个总的框架Fream怎么办?不会影响子框架?
    而且我看了看相关文档session="false"只是在本页面里session没有用,其实请求和超时的计算都还是在啊,根本没用,而且会导致其它问题,我要是想取seesion中的元素怎么办?
      

  8.   

    所以我说根本不需要Timer!只是单纯一个Filter就可以完成此功能
    public void doFilter(HttpServletRequest request,
    HttpServletResponse response, FilterChain chain) throws Exception {
    if(request.getRequestURI().equals(url)) {
    HttpSession session = request.getSession(false);
    if(session != null) {
    Date date = (Date) session.getAttribute("_LAST_ACCESS_TIME");
    if(System.currentTimeMillis() - date.getTime() > 10 * 60 * 1000) {
    session.invalidate();
    } else
    chain.doFilter(request, response);
    }
    } else {
    HttpSession session = request.getSession();
    session.setAttribute("_LAST_ACCESS_TIME", new Date());
    chain.doFilter(request, response);
    }
    }
      

  9.   

    10楼的办法固然很好,但是会让session延长存活时间,只是在“超时”以后不可再访问了。用这个办法吧,只需要注意session里别放什么违禁的东西。
    Timer么……嗯,过多的Timer恐怕更不好。这是个话题,值得讨论。
    是不是用一个专门的监控线程会好些?或者用一个全局的Timer,结合10楼的?
      

  10.   

    session也被销毁了,在之后的Ajax访问时由于调用的是request.getSession(false)所以不会创建新的Session,所以Session存活时间并不会延长。没有使用Timer的必要
      

  11.   

    10楼的方法我正在测试~~~感谢所有人!但是问题回到Timer中,按我上面的代码里面,应该Timer被清除了,可是实际上根本没有被清除,这是怎么回事?莫非Timer被放入的第一个任务是永远不会被取消的?