session already invalidate
// 涉及的主要代码
session.invalidate();
异常原因:
出现这个原因是因为这个session在之前已经invalidate了,有可能是因为我在web.xml中配置的<session-timeout>如下代码块,原理还不清楚,但是应该是session.invalidate()了,在代码中再次调用就出错了。
<session-config>
<session-timeout>1</session-timeout>
</session-config>
解决方案和思考:
在session.invalidate()外面加判断,判断这个session是否已经invalidate了。
但是有一个问题,通过DEBUG,我们可以知道,session有一个属性,叫isValid,调用invalidate()前,这个属性是true的,调用后就变成false了。并且invalidate()这个方法的原理不是销毁这个session对象,而是把isValid属性设置为true,并且把里面的信息全部清除,比如attribute信息等等,因为调用invalidate()后,session id仍然能获取到,并且session id不变。
经过百度后,我发现request.isRequestedSessionIDValid()暂时可以用来判断session是否已经invalidate()了,经过DEBUG发现,session.invalidate()前后request.isRequestedSessionIDValid()的返回值分别是true和false。我们来看一看request.isRequestedSessionIDValid()的官方介绍:
isRequestedSessionIDValid()介绍
方法名 | isRequestedSessionIDValid() |
介绍 | Checks whether the requested session ID is still valid. 检查所请求的会话ID是否仍然有效。 If the client did not specify any session ID, this method returns false. 如果客户端没有指定任何会话ID,则该方法返回false。 |
返回值 | true if this request has an id for a valid session in the current session context; false otherwise true:如果此请求在当前会话上下文中具有有效会话的ID false:否则 |
所以光判断request.isRequestedSessionIDValid()还不够,因为有可能客户端没有指定任何会话ID,还要判断session的值不为空,解决如下:
if (null != session && request.isRequestedSessionIdValid() != false) {
session.invalidate();
}
====================2017.3.21更新====================
request.isRequestedSessionIdValid()无法判断当前session是否已经invalidate
原因:
1. 在第一次服务启动时,重现异常的步骤,成功,invalidate()前为true,后为false。
2. 服务器不关闭,不重启的情况下,重现异常的步骤,invalidate()前后都为true,失败。
新的解决方案:
暂无
====================2017.3.21更新====================
====================2017.3.23更新====================
最终解决方案:
一直以来都有误区,没有好好利用监听器,我的想法是在session.invalidate()前,用session.setAttribute()添加一个标记,然后去监听器里判断,把标记放在一个Map中,这样程序里就可以判断了,这个功能是做另外一个功能的时候用的,碰巧这里也可以用。(此处情况多变,只提供思路,没有代码)
====================2017.3.23更新====================
建议:
最后建议如果要做session超时、不同设备的异地登陆等方法的时候,最好不要让session整个销毁来判断,而是手动在listener,inteceptor等类中手动控制,将用户对象添加/移除到session的attribute中来做操作,后期的坑会少一点。
后期已知的坑:
因为没办法判断session已经invalidate了,所以进行以下操作会报错,而且无法解决,还有常用的频率高的对attribute操作也会报错。
session.invalidate();
session.setAttribute("", "");
session.getAttribute("");