Załóżmy, że mam działającą aplikację Java oparta na języku Java z 0 lub więcej poprawnymi obiektami HttpSession
z nią powiązanymi. Chcę uzyskać dostęp do aktualnej listy ważnych obiektów HttpSession
. Myślałem, że mogę zaimplementować HttpSessionListener
i użyć go do dołączenia do listy wartości identyfikatora sesji, które są przechowywane w atrybucie o zasięgu aplikacji, ale wtedy jestem na bieżąco, aby zaktualizować listę, ponieważ sesje są unieważniane i kto wie co jeszcze.Jak uzyskać listę wszystkich obiektów HttpSession w aplikacji internetowej?
zanim zacznę pieczenia moje własne rozwiązanie pomyślałem, że powinienem zadać pytanie:
Czy API serwletów podać kilka sposobów na uzyskanie dostępu do pełnej listy niewyspecjalizowanych unieważnione obiektów sesji?
Używam Tomcat 6.x jako mojego kontenera aplikacji WWW i biblioteki MyFaces 1.2.x (JSF).
ROZWIĄZANIE
Śledziłem podejście podobne do tego, co BalusC omówione w tych istniejących pytań:
- 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
I zmodyfikowane przez SessionData
klasy wdrożyć HttpSessionBindingListener
. Gdy dojdzie do zdarzenia wiązania, obiekt albo doda, albo usunie się ze zbioru wszystkich obiektów 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);
}
}
Jedną rzeczą, która nadal mnie irytuje, jest to, co dzieje się po ponownym uruchomieniu Tomcata. O ile Tomcat nie został odpowiednio skonfigurowany do NIE serializowania sesji na dysku, zrobi to. Kiedy Tomcat ponownie się uruchamia, obiekty HttpSession
(i obiekty SessionData
wraz z nimi) są deserializowane i sesje są ponownie ważne. Jednak serializacja/deserializacja całkowicie omija zdarzenia detektora , więc nie mam możliwości z wdziękiem umieścić ponownie zserializowanego odwołania do SessionData
w moim zarządzanym zestawie obiektów po ponownym uruchomieniu.
Nie mam żadnej kontroli nad konfiguracją produkcyjną Tomcata w organizacji mojego klienta, więc nie mogę zakładać, że będzie to wykonane tak, jak tego oczekuję.
Moje obejście polega na porównaniu czasu utworzenia HttpSession
z czasem uruchomienia aplikacji po otrzymaniu żądania. Jeśli sesja została utworzona przed uruchomieniem aplikacji, wówczas zadzwonię pod numer invalidate()
, a użytkownik zostanie wysłany na stronę błędu/ostrzeżenia z wyjaśnieniem, co się stało.
Dostaję czas uruchomienia aplikacji poprzez wdrożenie ServletContextListener
i zapisanie bieżącego czasu wewnątrz obiektu o zasięgu aplikacji z metody contextInitialized()
mojego detektora.
Moja aplikacja będzie miała ograniczoną liczbę użytkowników w sieci prywatnej, więc nie będę musiał obsługiwać dystrybucji rozproszonej. Zgadzam się jednak z twoim komentarzem. –
Przypuszczam, że sposobem na zmianę tego (podobnie jak w przypadku upuszczania na dysku) byłoby uaktualnienie przez odbiornik udostępnionego magazynu danych (Redis, Memcached lub coś podobnego), który śledzi sesje. – Thilo