Как я могу закончить все мои сеансы в Tomcat? - PullRequest
10 голосов
/ 18 октября 2010

Я хотел бы закончить все мои сеансы в Tomcat. Мы тестируем наш продукт под Fitnesse, и некоторые сеансы остаются, и конец сеанса вызывает зависимость между тестами. Я делаю это вручную с помощью следующего кода, но некоторые сеансы остаются (я могу проверить это с помощью http://localhost:8080/manager/html/list url)

public static void expireAllSessions() {
    String[] applications = { "a", "b", "c", "d",  "e" };
    for (String application : applications) {
        try {
            expireAllSessions(application);
        } catch (Exception e) {
            logger.error(e);
        }
    }
}

private static void expireAllSessions(final String application) throws Exception {
    // cf doc http://hc.apache.org/httpclient-3.x/authentication.html
    HttpClient client = new HttpClient();
    client.getParams().setAuthenticationPreemptive(true);
    Credentials userPassword = new UsernamePasswordCredentials("tomcat", "tomcat");
    client.getState().setCredentials(AuthScope.ANY, userPassword);

    String url = "http://localhost:8080/manager/html/expire";
    NameValuePair[] parametres = new NameValuePair[] {
            new NameValuePair("path", "/" + application),
            new NameValuePair("idle", "0")
    };
    HttpMethod method = new GetMethod(url);
    method.setQueryString(parametres);
    client.executeMethod(method);
}

Есть ли способ сделать это более эффективно и немедленно, без оставшегося сеанса?

Ответы [ 3 ]

7 голосов
/ 19 октября 2010

Я предполагаю, что ваши приложения действительно независимы.Я сделал нечто похожее на то, что вы просите, используя HttpSessionListener для каждого контекста.Сложность в том, что вам нужно иметь Session Collection, которая загружается загрузчиком корневого класса, а не загрузчиком контекстного класса.Вот как я помню это:

Создайте класс, который содержит активные сеансы для каждого контекста.Этот класс должен находиться в каталоге tomcat / lib, чтобы он был доступен для каждого контекста.Он не может быть частью какого-либо из контекстов.

public class SessionMap {

  private static Map<ServletContext, Set<HttpSession>> map =
    new HashMap<ServletContext, Set<HttpSession>>();

  private SessionMap() {
  }

  public static Map<ServletContext, Set<HttpSession>> getInstance() {
    return map;
  }

  public static void invalidate(String[] contexts) {
    synchronized (map) {
      List<String> l = Arrays.asList(contexts);     
      for (Map.Entry<ServletContext, Set<HttpSession>> e : map.entrySet()) {
        // context name without the leading slash
        String c = e.getKey().getContextPath().substring(1);
        if (l.contains(c)) {
          for (HttpSession s : e.getValue()) 
            s.invalidate();
        }
      }
    }
  }

}

Создать слушателя для каждого контекста.

public class ApplicationContextListener implements HttpSessionListener {

  public void sessionCreated(HttpSessionEvent event) {
    ConcurrentMap<ServletContext, Set<HttpSession>> instance = SessionMap.getInstance();
    synchronized (instance) {
      ServletContext c = event.getSession().getServletContext();
      Set<HttpSession> set = instance.get(c);
      if (c == null) {
        set = new HashSet<HttpSession>();
        instance.put(c, set);
      }
      set.add(event.getSession());
    }
  }

  public void sessionDestroyed(HttpSessionEvent event) {
    ConcurrentMap<ServletContext, Set<HttpSession>> instance = SessionMap.getInstance();
    synchronized (map) {
      ServletContext c = event.getSession().getServletContext();
      Set<HttpSession> set = instance.get(c);
      if (c != null) {
        set.remove(event.getSession());
      }
    }
  }

}

Зарегистрировать каждого слушателя в соответствующем контексте web.xml.

<listener>
  <listener-class>ApplicationContextListener</listener-class>
</listener>

Затем вы можете вызвать следующую строку, чтобы сделать недействительным все из любого контекста.

SessionMap.invalidate();

Я синхронизируюсь на карте, чтобы быть в безопасности.

3 голосов
/ 18 октября 2010

Вы можете использовать HttpSessionListener, чтобы сохранить ссылки на сеансы в структуре данных, а затем использовать их на досуге

1 голос
/ 18 октября 2010

Вы смотрели на Лямда-зонд ? Для каждого из ваших веб-приложений вы можете просмотреть содержимое сеанса и завершить его (все).

alt text

Если вы хотите написать собственное приложение, чтобы сделать это вместо этого; Lamda Probe имеет открытый исходный код, поэтому вы можете взять у них код для достижения своей цели.

...