浏览 4287 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2012-09-20
最后修改:2012-09-20
session.isValid()//判断当前session对象是否还有效 session.expiring //是否过期 因为项目需要判断当前session是否有效或者过期,然后需要做一些处理(细节就不多说了) 设置的tomcat某个项目的session过期时间是30分钟 但是问题就出现了,问题如下: 当我调用了session.isValid()和session.expiring查看时发现, session很短的时间内就会被判断为无效,因为我页面没有一直刷新可能也就一分钟左右没操作页面, 但是这个session时候并没有过期. 有效测试:session.isValid()返回 false //session已经是无效了 过期测试:session.expiring 返回 false //说明没有过期 我想问大家的是在session没有过期时期,这个判断无效(isValid())的方法运行的原理是什么? 当前session是否真的是无效了 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2012-09-20
引用 public boolean isValid()
{ if (this.expiring) { //如果已经过期返回true return true; } if (!(this.isValid)) { //如果没有过期 则返回false return false; } if ((ACTIVITY_CHECK) && (this.accessCount.get() > 0)) { return true; } if (this.maxInactiveInterval >= 0) { //判断当前访问时间-上次访问时间 如果超过maxInactiveInterval 过期session long timeNow = System.currentTimeMillis(); int timeIdle = (int)((timeNow - this.thisAccessedTime) / 1000L); if (timeIdle >= this.maxInactiveInterval) { expire(true); //过期方法 } } return this.isValid; } 引用 public void expire(boolean notify)
{ if (this.expiring) { return; } synchronized (this) { if (this.manager == null) { return; } this.expiring = true; //设置expiring=true Context context = (Context)this.manager.getContainer(); Object[] listeners = context.getApplicationLifecycleListeners(); if ((notify) && (listeners != null)) { HttpSessionEvent event = new HttpSessionEvent(getSession()); for (int i = 0; i < listeners.length; ++i) { int j = listeners.length - 1 - i; if (!(listeners[j] instanceof HttpSessionListener)) continue; HttpSessionListener listener = (HttpSessionListener)listeners[j]; try { fireContainerEvent(context, "beforeSessionDestroyed", listener); listener.sessionDestroyed(event); fireContainerEvent(context, "afterSessionDestroyed", listener); } catch (Throwable t) { try { fireContainerEvent(context, "afterSessionDestroyed", listener); } catch (Exception e) { } this.manager.getContainer().getLogger().error(sm.getString("standardSession.sessionEvent"), t); } } } if (ACTIVITY_CHECK) { this.accessCount.set(0); } setValid(false); //设置已经过期 long timeNow = System.currentTimeMillis(); int timeAlive = (int)((timeNow - this.creationTime) / 1000L); synchronized (this.manager) { if (timeAlive > this.manager.getSessionMaxAliveTime()) { this.manager.setSessionMaxAliveTime(timeAlive); } int numExpired = this.manager.getExpiredSessions(); ++numExpired; this.manager.setExpiredSessions(numExpired); int average = this.manager.getSessionAverageAliveTime(); average = (average * (numExpired - 1) + timeAlive) / numExpired; this.manager.setSessionAverageAliveTime(average); } this.manager.remove(this); if (notify) { fireSessionEvent("destroySession", null); } this.expiring = false; //expiring改为false String[] keys = keys(); for (int i = 0; i < keys.length; ++i) removeAttributeInternal(keys[i], notify); } } 即expiring表示正在过期这个行为,不表示是否过期这个状态,过期行为执行完毕后再改为false 如果session过期isValid()肯定为false。 如果你是通过类似于如下代码得到StandardSession private StandardSession getStandardSession(HttpSession session) { try { StandardSessionFacade sessionFacade = (StandardSessionFacade) session; Field f = sessionFacade.getClass().getDeclaredField("session"); f.setAccessible(true); StandardSession standardSession = (StandardSession) f.get(sessionFacade); return standardSession; }catch (Exception e) { e.printStackTrace(); return null; } } 则我认为这个StandardSession一直是不过期的(因为你过期了会再创建一个新的session的) 如果你是在session创建的时候把它保存下来(如放到一个Map),那调用isValid()可能返回false(这个销毁速度跟MaxInactiveInterval/直接调用invalidate有关)。 不建议使用那两个东西进行session是否过期的处理;而是要根据session是否销毁做特殊处理的话 直接用HttpSessionListener多好。 这种判断可能不正确,如session销毁了 则下次请求时得到的是一个新的session;而且你现在得到的是tomcat实现,那可能在其他类型服务器可能不好使,建议还是使用标准API来做。 |
|
返回顶楼 | |
发表时间:2012-09-21
最后修改:2012-09-21
谢谢楼上的回答和提醒,我会继续去看API和源代码研究的!
以下是我自定义的session备份,调用的是tomcat提供的backgroundProcess方法 这里我就用到了 判断session过期和是否有效的方法,发现session.isValid()会很就返回session已经无效了,但此时并没有过期. /** * tomcat中定期执行的方法,用于更新memcached中的对象保存时间 * 延迟的时间设置 context.xml文件context节点上的backgroundProcessorDelay属性. 单位:秒 */ @Override public void backgroundProcess() { try { this.updateExpirationInMemcached(); } catch (Exception e) { e.printStackTrace(); } super.backgroundProcess(); } /** * 定时更新session,更新session在memcached中的时间 * @throws Exception */ private void updateExpirationInMemcached() throws Exception { Session [] sessions = super.findSessions(); for(Session tmpSession: sessions){ MemcachedSession session = (MemcachedSession)tmpSession; if(!session.isValid()||session.isExpiring()){ System.out.println(session.getId() + "--有效:" + session.isValid() + "--过期:" + session.isExpiring()); System.out.println("该会话已经过期了,从memcached中删除!"); this.getMemcacheds().deleteKeyValue(session.getId()); continue; } if("true".equalsIgnoreCase(this.sessionSticky)){ //异步的更新方法 if("binary".equalsIgnoreCase(this.protocol)){ this.getMemcacheds().updateExpiringTime(session.getId()); }else if("text".equalsIgnoreCase(this.protocol)){ this.getMemcacheds().setValueNoWait(session.getId(),session); } }else{ //同步的更新方法,因为非粘连情况,必须保证session一致性 if("binary".equalsIgnoreCase(this.protocol)){ this.getMemcacheds().updateExpiringTime(session.getId()); }else if("text".equalsIgnoreCase(this.protocol)){ this.getMemcacheds().setValue(session.getId(),session); } } } } |
|
返回顶楼 | |
发表时间:2012-09-21
那你应该连Session的 Manager 都替换掉啊 不应该混用啊
http://hi.baidu.com/drnadmhzfnacefe/item/87cead68940ef408a1cf0fa2 |
|
返回顶楼 | |
发表时间:2012-09-21
tomcat中的session超时时间不是可以设置的吗
|
|
返回顶楼 | |
发表时间:2012-09-22
public boolean isValid() { if (this.expiring) { //如果已经过期返回true return true; } 。。。。。。 有点不明白,既然已经在做session的过期处理了,那说明当前session的随时会被销毁。为什么还要返回true啊? |
|
返回顶楼 | |