Нет доступа к списку активных HttpSession
.
Это изменение произошло для поддержки постоянного улучшения управления сеансами для обработки распределенных SessionDataStores
и распределенных серверов без привязки к сеансам (например, для многих облачных предложений).
Было бы лучше, если бы вы сами отслеживали HttpSessions
на стороне сервера.
Как это сделать ...
Реализация пользовательского прослушивателя сеанса.Убедитесь, что он реализует javax.servlet.http.HttpSessionListener
и javax.servlet.http.HttpSessionIdListener
для отслеживания сеансов, которые были созданы / уничтожены / изменены.(может также потребоваться реализация javax.servlet.ServletContextListener
для остановки отслеживания сеансов в разрушенном контексте)
Убедитесь, что вы отслеживаете сеансы только по их идентификаторам (и, необязательно, какому контексту они принадлежат) в этой реализации.(не храните ссылку на объект HttpSession, иначе вы испортите жизненный цикл GC и WebApp).
Пример:
public static class SessionTracker implements HttpSessionListener,
HttpSessionIdListener, ServletContextListener
{
private final Server server;
private final SessionHandler sessionHandler;
private String contextPath;
private HashSet<String> sessionIds = new HashSet<>();
public SessionTracker(Server server, SessionHandler sessionHandler)
{
this.server = server;
this.sessionHandler = sessionHandler;
this.sessionHandler.addEventListener(this);
}
public String getContextPath()
{
return contextPath;
}
public SessionHandler getSessionHandler()
{
return sessionHandler;
}
public HashSet<String> getSessionIds()
{
return sessionIds;
}
@Override
public void contextInitialized(ServletContextEvent sce)
{
contextPath = sce.getServletContext().getContextPath();
}
@Override
public void contextDestroyed(ServletContextEvent sce)
{
Collection<SessionTracker> trackers = this.server.getBeans(SessionTracker.class);
trackers.removeIf((tracker) -> tracker.getContextPath().equals(sce.getServletContext().getContextPath()));
}
@Override
public void sessionCreated(HttpSessionEvent se)
{
sessionIds.add(se.getSession().getId());
}
@Override
public void sessionDestroyed(HttpSessionEvent se)
{
sessionIds.remove(se.getSession().getId());
}
@Override
public void sessionIdChanged(HttpSessionEvent event, String oldSessionId)
{
sessionIds.add(oldSessionId);
sessionIds.add(event.getSession().getId());
}
}
И способ добавить это ко всемправильно контексты ...
// After server.start() somewhere.
addSessionTracker(server.getHandler());
private static void addSessionTracker(Handler handler)
{
if (handler == null)
{
return; // skip
}
if (handler instanceof HandlerCollection)
{
HandlerCollection handlers = (HandlerCollection) handler;
for (Handler child : handlers.getHandlers())
{
addSessionTracker(child);
}
}
else
{
if (handler instanceof ServletContextHandler)
{
ServletContextHandler context = (ServletContextHandler) handler;
SessionHandler sessionHandler = context.getSessionHandler();
new SessionTracker(handler.getServer(), sessionHandler);
}
}
}
Затем, чтобы использовать эти трекеры ...
private static void doSomethingWithSessionTracker(Server server)
{
Collection<SessionTracker> trackers = server.getBeans(SessionTracker.class);
trackers.forEach((tracker) -> {
tracker.getSessionIds().forEach((sessionId) -> {
Session session = tracker.getSessionHandler().getSession(sessionId);
// Do something with Session.
});
});
}
Обратите внимание, что выше будет только показать сеанс отслеживается на этом сервере,Если у вас есть несколько серверов или распределенное хранилище сеансов, вы не увидите сеансы с других серверов.Если это важно для вас, подумайте о написании собственного SessionDataStore
, который позволит вам получить доступ к сохраненному Sessions
.