Предположим, у меня есть работающее веб-приложение на основе Java с 0 или более действительными HttpSession
объектами, связанными с ним. Я хочу получить доступ к текущему списку допустимых объектов HttpSession
. Я думал, что могу реализовать HttpSessionListener
и использовать его для добавления в список значений идентификатора сеанса, которые хранятся в атрибуте области приложения, но затем я нахожусь на крючке, чтобы обновить список, поскольку сеансы являются недействительными и кто знает что еще.Как получить список всех объектов HttpSession в веб-приложении?
Перед тем, как начать выпечки мое собственное решение, я думал, что я должен задать вопрос:
Предоставляет ли сервлет API некоторые средства получения доступа к полному списку недействующих недействительными сессии объектов?
Я использую Tomcat 6.x в качестве контейнера для веб-приложений и библиотеки MyFaces 1.2.x (JSF).
РЕШЕНИЕ
Я последовал за подход, аналогичный тому, что BalusC обсуждается в этих существующих вопросов:
- How to easily implement "who is online" in Grails or Java Application ?
- JSF: How to invalidate an user session when he logs twice with the same credentials
Я модифицируется 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 в организации моего клиента, поэтому я не могу предположить, что это будет сделано так, как я ожидаю.
Моим обходным путем является сравнение времени создания с временем запуска приложения при получении запроса. Если сеанс был создан до времени запуска приложения, я вызываю invalidate()
, и пользователь отправляется на страницу с ошибкой/предупреждением с объяснением произошедшего.
Я получаю время запуска приложения, реализуя ServletContextListener
и сохраняя текущее время внутри объекта с областью приложения из метода contextInitialized()
моего слушателя.
Мое приложение будет иметь ограниченное количество пользователей в частной сети, поэтому мне не нужно поддерживать распределенное развертывание. Однако я согласен с вашим комментарием. –
Я предполагаю, что способ изменить это (а также настойчивость на диске) будет состоять в том, чтобы прослушиватель обновил общий хранилище данных (Redis, Memcached или что-то еще), которое отслеживает сеансы. – Thilo