【问题标题】:request.getSession(false) causes java.lang.IllegalStateExceptionrequest.getSession(false) 导致 java.lang.IllegalStateException
【发布时间】:2011-08-15 11:23:24
【问题描述】:

当我尝试从请求中获取会话时,如果会话过期,则会导致空指针异常。下面给出的是代码的一部分。我在第三行得到异常。

public void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) req;
HttpSession session = httpReq.getSession(false);

这里是堆栈跟踪:

java.lang.IllegalStateException: getLastAccessedTime: Session already invalidated
at org.apache.catalina.session.StandardSession.getLastAccessedTime(StandardSession.java:423)
at org.apache.catalina.session.StandardSessionFacade.getLastAccessedTime(StandardSessionFacade.java:84)
at com.myapp.admin.CustomerContext.valueUnbound(CustomerContext.java:806)
at org.apache.catalina.session.StandardSession.removeAttributeInternal(StandardSession.java:1686)
at org.apache.catalina.session.StandardSession.expire(StandardSession.java:801)
at org.apache.catalina.session.StandardSession.isValid(StandardSession.java:576)
at org.apache.catalina.connector.Request.doGetSession(Request.java:2386)
at org.apache.catalina.connector.Request.getSession(Request.java:2120)
at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:833)
at com.myapp.ui.web.filter.ApplicationSessionFilter.doFilter(ApplicationSessionFilter.java:45)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.myapp.ui.web.filter.ErrorFilter.doFilter(ErrorFilter.java:42)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:190)
at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:291)
at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:776)
at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:705)
at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:898)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690)
at java.lang.Thread.run(Thread.java:662)

【问题讨论】:

  • 可能没有任何会话附加到他的请求。因为如果你没有创建任何会话,getSession(fasle) 返回 null。

标签: java tomcat servlets tomcat6


【解决方案1】:

这不是空指针异常。
这是非法状态异常。

当会话已失效/过期并且您尝试访问它时会发生这种情况。

会话失效如下。

session.invalidate();

invalidate 调用后,无法使用会话。

会话在超时时过期。过期后,如果你尝试使用它,它会抛出同样的异常。

这些是您可以手动设置超时的方法。

在 web.xml 中设置超时。这是在几分钟内设置的。

<session-config>
   <session-timeout>30</session-timeout> 
</session-config>

或者你也可以在你的java中设置它。

public void setMaxInactiveInterval(int interval)

session.setMaxInactiveInterval(30*60); // This we set in seconds. 

这里我们指定客户端请求之间的时间,以秒为单位,在 servlet 容器将使该会话无效之前。负时间表示会话永远不会超时。

确保您正在执行的操作不会超过超时时间。否则,您将不得不重置该值。

编辑:
不可能以干净的方式从中恢复。该会话将失效/不可用,您将需要创建一个新会话并重新填充数据。 通常人们会被重定向到另一个错误页面,而不是显示堆栈跟踪。 “您的会话已过期。请重新登录。”

使用 request.isRequestedSessionIdValid() 来识别会话 ID 是否仍然有效。

HttpSession session =httpReg.getSession(false);
if( !request.isRequestedSessionIdValid() )
{
        //comes here when session is invalid.
        // redirect to a clean error page "Your session has expired. Please login again."
}

另一种选择是使用 try catch 处理 IllegalExceptionState

HttpSession session =httpReg.getSession(false);
try
{
     if(session != null)
     { 
       Date date = new Date(session.getLastAccessedTime()); 
    }
}
catch( IllegalStateException ex )
{
      //comes here when session is invalid.
      // redirect to a clean error page "Your session has expired. Please login again."
}

旁注: 如果您确实有一个需要很长时间才能完成的过程并且会话超时(例如:解析非常大的数据记录)。 您应该考虑将它们从 Web 应用程序中取出,并使用简单的 java 将它们作为进程运行。

【讨论】:

  • 感谢您的评论.. 但我总是在使用会话之前检查空值。从日志中我可以看到第 3 行的异常原因。
  • @code247,这可能无关紧要,但出于好奇,这行发生了什么? com.myapp.admin.CustomerContext.valueUnbound(CustomerContext.java:806)
  • @kensen 这就是 806 发生的事情 :) if(session != null){ date = new Date(session.getLastAccessedTime()); }。试图从会话中获取上次访问时间。但在此之前有一个空检查。
  • @coder247 我编辑了我的答案。请检查一下。这不是 NullPointer 异常。这是一个 IllegalStateException,因为会话无效。
  • 当我在会话超时后尝试访问该页面时出现此异常。当前会话超时为 30 分钟。在那之前没有问题,30分钟的空闲时间后会发生异常。
【解决方案2】:

您的异常表明您已通过调用 .invalidate() 使会话无效,但正在尝试使用它。这不可能。

每当您invalidate() 会话时,请不要再使用它。

【讨论】:

    猜你喜欢
    • 2012-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-17
    • 2013-01-11
    • 1970-01-01
    • 2019-05-03
    相关资源
    最近更新 更多