Java 为什么在HttpSessionListener中调用invalidate()不';不要给StackOverflower错误?

Java 为什么在HttpSessionListener中调用invalidate()不';不要给StackOverflower错误?,java,jakarta-ee,listener,stack-overflow,httpsession,Java,Jakarta Ee,Listener,Stack Overflow,Httpsession,我有一个jsp文件和一个HttpSessionListener来监视HttpSession销毁活动 index.jsp <% HttpSession s = request.getSession(); System.out.println("SID1 : " + s.getId()); s.setAttribute("Key", "Value"); s.invalidate(); %> 现在根据上述情况,向index.jsp发送HTTP请求应该创建一

我有一个
jsp
文件和一个
HttpSessionListener
来监视
HttpSession
销毁活动

index.jsp

<%
    HttpSession s = request.getSession();
    System.out.println("SID1 : " + s.getId());
    s.setAttribute("Key", "Value");
    s.invalidate();
%>
现在根据上述情况,向
index.jsp
发送HTTP请求应该创建一个
HttpSession
并调用它的
invalidate()
方法,同时
HttpSessionListener
应该捕获相同的
HttpSession
并再次调用
invalidate()
,这个过程应该一次又一次地重复

这最终会导致抛出一个
java.lang.StackOverflowerError
。但是我得到了以下输出,没有任何错误。

SID1 : A2751AE9E782A17380415B0078C9ED90
SID2 : A2751AE9E782A17380415B0078C9ED90
Value
Session Destroyed

我已经用GlassFish和Tomcat服务器对其进行了测试,结果保持不变。有人能解释发生了什么吗?

显然,这是因为当您从
public void sessionDestroyed(HttpSessionEvent se){…}
第二次调用
invalidate
方法时,会话已经失效

Session.beginInvalidate()
在这种情况下返回
false
值,并且不调用此块:

boolean result = beginInvalidate();

try {
    //if the session was not already invalid, or in process of being invalidated, do invalidate
    if (result) {
         //tell id mgr to remove session from all contexts
         _handler.getSessionIdManager().invalidateAll(_sessionData.getId());
    }
}
特别是,
\u handler.getSessionIdManager().invalidateAll
调用
SessionHandler.invalidate
,调用
SessionHandler.removeSession
,调用
\u sessionListeners.get(i).sessionDestroyed(事件)


因此,如果会话已无效,则此场景不起作用。

为什么要抛出
StackOverflowerError
?HttpSession.invalidate()上的函数提到,如果在已经失效的会话上调用此方法,则它应该抛出
IllegalStateException
。这可能是您正在使用的特定应用程序服务器的一个怪癖/错误。能否在jsp中的s.invalidate()之后打印request.getSession().isNew(),并告诉我们结果?会话不会在第一次失效。看看会话ID。它们是一样的。所以它应该不断地调用invalidateagain@techtrainer在
jsp
文件中?在jsp文件中是的,如注释中所述。如果会话已经无效,那么在侦听器中调用时,属性如何在输出中打印出来?我不理解您的最后一个问题。有什么问题吗?第一次调用
s.invalidate()来自JSP。它完成了我在回答中描述的所有顺序。之后,将在执行所有打印输出的位置调用您的
sessionDestroyed
。然后再次调用那里的
s.invalidate()
,但它没有效果,因为此时会话已经无效。
boolean result = beginInvalidate();

try {
    //if the session was not already invalid, or in process of being invalidated, do invalidate
    if (result) {
         //tell id mgr to remove session from all contexts
         _handler.getSessionIdManager().invalidateAll(_sessionData.getId());
    }
}