#java #tomcat #servlets #tomcat6
#java #tomcat #сервлеты #tomcat6
Вопрос:
Когда я пытаюсь получить сеанс из запроса, это вызывает исключение с нулевым указателем, если срок действия сеанса истек. Приведенное ниже является частью кода. Я получаю исключение в третьей строке.
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)
Комментарии:
1. Возможно, к его запросу не привязан какой-либо сеанс. потому что getSession (fasle) возвращает null, если вы не создали никаких сеансов.
Ответ №1:
Это не исключение Nullpointer.
Это исключение из недопустимого состояния.
Это происходит, когда сеанс признан недействительным / истек, и вы пытаетесь получить к нему доступ.
Сеанс становится недействительным следующим образом.
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.
Здесь мы указываем время в секундах между запросами клиента, прежде чем контейнер сервлета аннулирует этот сеанс. Отрицательное время указывает, что сеанс никогда не должен прерываться.
Убедитесь, что выполняемая вами операция не занимает больше времени, чем время ожидания. В противном случае вам придется сбросить значение.
Редактировать:
Восстановить его чистым способом невозможно. Сеанс станет недействительным / непригодным для использования, и вам нужно будет создать новый сеанс и повторно заполнить данные. Обычно пользователи перенаправляются на альтернативную страницу с ошибкой вместо отображения трассировки стека. «Срок действия вашего сеанса истек. Пожалуйста, войдите еще раз.»
Используйте request.isRequestedSessionIdValid(), чтобы определить, действителен ли идентификатор сеанса.
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."
}
Другой вариант — использовать обработку состояния IllegalExceptionState с помощью try catch
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."
}
Примечание сбоку:
Если у вас есть процесс, для завершения которого требуется много времени, и время ожидания сеансов истекает (например: разбор действительно больших записей данных).
Вам следует рассмотреть возможность удаления их из веб-приложения и использовать простую Java для запуска их как процесса.
Комментарии:
1. Спасибо за комментарий.. но я всегда проверяю значение null перед использованием сеанса. И из журнала я вижу, что исключение возникает в строке 3.
2. @code247, это может быть неуместно, но из любопытства, что происходит в этой строке? com.myapp.admin.CustomerContext.valueUnbound(CustomerContext.java:806)
3. @kensen это то, что происходит в 806 🙂 if(session != null){ date = новая дата (session.getLastAccessedTime()); }. Пытаюсь получить время последнего доступа из сеанса . Но перед этим выполняется проверка null.
4. @coder247 Я отредактировал свой ответ. пожалуйста, проверьте это. Это не было исключением NullPointer. Это было исключение IllegalStateException, потому что сеанс был признан недействительным.
5. Я получаю это исключение, когда пытаюсь получить доступ к странице после истечения времени сеанса. Время ожидания текущего сеанса составляет 30 минут. И до этого времени проблем нет, после 30 минут простоя происходит исключение.
Ответ №2:
Ваше исключение показывает, что вы аннулировали сеанс, вызвав .invalidate()
, но пытаетесь его использовать. Это невозможно.
Всякий раз, когда вы invalidate()
запускаете сеанс, больше не используйте его.