`
energykey
  • 浏览: 592889 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

关于session、invalidate()、request.getSession(boolean)的一点实验

阅读更多
今天发现jboss给我丢出了一个错误。
"Session already invlidated!"

于是开始寻找这个BUG的原因,后来发现时我代码里有一句session.invalidate();
由于session是有效期的,也就是说web容器会在有效期到了之后把到期的session彻底清除。
但是我写这段代码的时候显然并没有考虑到这个。所以当一个失效的session被我执行invalidate()操作时报错了这个错误。

解决办法。

思路1:
session.invalidate()执行前先判断这个session是否已经invalid。
google了一下,看了下API,session并没有提供相关的方法,只能间接通过HttpSessionListener监听session的销毁然后将其保存至某变量实现。显然,这不是我想要的。

思路2:
利用异常,既然你抛异常,那我就捕捉异常。
对这句话加一个try{}catch{},显然,catch后就知道这个session已经invalid.

问题解决了,顺便研究了一下session的机制。通过跟踪发现,session.invalidate()方法只是将session得isValid属性设置为了false,而此时的session并没有销毁,其他属性如id等依然存有数据。但是我们看一下API的描述
invalidate() 
          Invalidates this session then unbinds any objects bound to it.

这里不仅仅是把isValid设置为了false,还解除这个session和其他任何对象的关联,也就是说,这个session虽然是存在的,但是是游离的,是孤立的。

所以,通过request.getSession(false);你将得到的是null,虽然session存在,但已和request解除绑定了。

那么为什么会这样?

我没有去看源代码,但是可以推理,session是由web容器管理的,众所周知,大量的对象创建和销毁操作会消耗很多的资源,所以这个session通过一个maxInactiveInterval属性来缓存在web容器里,这样当你再有效期内重新请求web容器,则web容器只需要isValid属性恢复为true,然后这个session又可以分配给你了。

我做了个实验,代码如下
HttpSession currentsession = request
					.getSession();
			request.getSession().invalidate();
			request.getSession(false);

我在1分钟内执行了上面代码两次,两次获得的session id是一致的。

再次声明小弟没有看源代码,这里只是根据实验推测而已,如有不对的地方,还望指正。

最后指出一点
sessionDestroyed
public void sessionDestroyed(HttpSessionEvent se)
Notification that a session was invalidated.
Parameters:
se - the notification event



sessionDestroyed事件只要session invalidated就会触发,当然web容器彻底销毁session的时候也会触发。
5
0
分享到:
评论
2 楼 chaifuzhi1025 2012-08-01  
有时候会出现:if(!request.getSession().isNew() && request.getSession()!=null){
request.getSession().invalidate();
}
 
session = request.getSession(true);
重新建立session不会刷新,即sessionid不会变化。可以再相应提供服务(如:jboss)的server.xml中修改:

    <Connector port="8080" address="${jboss.bind.address}"   
         maxThreads="250" maxHttpHeaderSize="8192"
         emptySessionPath="false" protocol="HTTP/1.1"
         enableLookups="false" redirectPort="8443" acceptCount="100"
         connectionTimeout="20000" disableUploadTimeout="true" />

1 楼 skybusy2000 2010-02-22  
我现在使用的是第一种方法:
public static boolean onLogin(HttpSession session, String loginId) {
String sessionId = session.getId();
HttpSession oldSession;
synchronized(mapLoginId2Session) {
oldSession = mapLoginId2Session.get(loginId);
mapSessionId2Login.put(sessionId, loginId);
mapLoginId2Session.put(loginId, session);
}

if ((oldSession != null)&&(oldSession != session)) {
try{
oldSession.invalidate();
}catch(Exception e){
logger.error("LoginSessionListener Exception:"+e.getMessage());
}
mapLoginId2Session.put(loginId, session);
mapSessionId2Login.put(sessionId, loginId);
return true;
}
return false;
}
public static void onLogout(HttpSession session) {
String sessionId = session.getId();
synchronized(mapLoginId2Session) {
String loginId = mapSessionId2Login.get(sessionId);
if (loginId != null) {
mapLoginId2Session.remove(loginId);
mapSessionId2Login.remove(sessionId);
}
}
}

每次session无效的时候会维护这个mapLoginId2Session的map,这样每次当我使用oldSession.invalidate();方法时 就可以保证 这个session肯定没有无效过  但有时候还是会抛出Session already invlidated!异常 搞不懂了

相关推荐

Global site tag (gtag.js) - Google Analytics