Встроенный причал: отображать все сеансы в контексте - PullRequest
0 голосов
/ 28 января 2019

Я недавно переместил проект, использующий встроенную Jetty, с версии 6.1 до 9.4.Это было проще, чем я ожидал.Теперь для переноса остается только одна функция: в проекте есть инструмент администрирования, который показывает все загруженные контексты (он может содержать более одного веб-приложения), а для каждого контекста - список зарегистрированных сеансов HTTP, включая атрибуты сеанса и т. Д.Jetty 6, это выглядит примерно так:

Handler[] handlers = jettyServer.getHandlers();
for (Handler h : handlers) {
  if (h instanceof ContextHandlerCollection) {
    ContextHandlerCollection ch = (ContextHandlerCollection) h;
    Handler[] contexts = ch.getHandlers();
    for (Handler context : contexts) {
      if (context instanceof WebAppContext) {
        WebAppContext wapp = (WebAppContext) context;
        // Here, I am stuck in migrating this to jetty 9:
        SessionManager sm = wapp.getSessionHandler().getSessionManager();
        if (sm instanceof HashSessionManager) {
          HashSessionManager hsm = (HashSessionManager) sm;
          Map<?,?> sessions = hsm.getSessionMap();
          if (sessions != null) {
            for (Map.Entry<?,?>  entry : sessions.entrySet()) {
              if (entry.getValue() instanceof HttpSession) {
                HttpSession s = (HttpSession) entry.getValue();
              }
            }
          }
        }
      }
    }
  }
}

Новая структура Jetty 9 немного отличается, но я смог получить доступ ко всем контекстам.Но в Jetty 9 я не могу получить доступ к SessionManager из контекста.

wapp.getSessionHandler().getSessionManager();

Больше не работает, метод getSessionManager() в SessionHandler больше не существует.И после поисков в течение нескольких часов я не нашел способа получить от WebAppContext до HTTPSession экземпляров в этом контексте.Кто-нибудь знает способ туда добраться?

1 Ответ

0 голосов
/ 01 февраля 2019

Нет доступа к списку активных 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.

...