Скажем, у меня есть запущенное веб-приложение на основе Java с 0 или более допустимыми HttpSession
объектами, связанными с ним. Я хочу получить доступ к текущему списку допустимых объектов HttpSession
. Я думал, что могу реализовать HttpSessionListener
и использовать его для добавления к списку значений идентификатора сеанса, которые хранятся в атрибуте области приложения, но затем я нахожусь на крючке, чтобы обновить список, поскольку сеансы являются недействительными и кто знает, что еще.
Прежде чем я начну выпекать свое собственное решение, я подумал, что должен задать вопрос:
Предоставляет ли сервлет-API некоторые способы получения доступа к полному списку недействительных объектов сеанса?
Я использую Tomcat 6.x в качестве контейнера для веб-приложений и библиотеки MyFaces 1.2.x(JSF).
Решение
Я следовал подходу, подобному тому, что BalusC обсуждал в этих существующих вопросах:
- Как легко реализовать" кто онлайн "в приложении Grails или Java ?
- JSF: как аннулировать пользовательский сеанс, когда он дважды регистрируется с помощью те же учетные данные
Я модифицировал класс SessionData
для реализации HttpSessionBindingListener
. Когда происходит событие привязки, объект будет либо добавлять, либо удалять себя из набора всех объектов SessionData
.
@Override
public void valueBound(HttpSessionBindingEvent event) {
// Get my custom application-scoped attribute
ApplicationData applicationData = getApplicationData();
// Get the set of all SessionData objects and add myself to it
Set<SessionData> activeSessions = applicationData.getActiveSessions();
if (!activeSessions.contains(this)) {
activeSessions.add(this);
}
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
HttpSession session = event.getSession();
ApplicationData applicationData = getApplicationData();
Set<SessionData> activeSessions = applicationData.getActiveSessions();
if (activeSessions.contains(this)) {
activeSessions.remove(this);
}
}
Единственное, что меня раздражает, это то, что происходит, когда Tomcat перезапускается. Если Tomcat не был настроен правильно, чтобы НЕ сериализовать сеансы на диск, он сделает это. Когда Tomcat снова запускается, объекты HttpSession
(и объекты SessionData
вместе с ними) десериализуются, и сеансы снова становятся действительными. Однако сериализация/десериализация полностью обходит события HttpSession
прослушивателя, поэтому у меня нет возможности изящно помещать десериализованную ссылку на SessionData
обратно в управляемый набор объектов после перезапуска.
У меня нет контроля над производственной конфигурацией Tomcat в моей организации-заказчике, поэтому я не могу предположить, что это будет сделано так, как я ожидаю.
Мое обходное решение - сравнить время создания HttpSession
со временем запуска приложения при получении запроса. Если сеанс был создан до времени запуска приложения, я вызываю invalidate()
, и пользователь отправляется на страницу с ошибкой/предупреждением с объяснением того, что произошло.
Я получаю время запуска приложения, реализуя ServletContextListener
и сохраняя текущее время внутри объекта с областью приложения из метода contextInitialized()
моего слушателя.