如何在Tomcat中使所有会话过期?

10

我想要在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个回答

8
我假设您的应用程序是真正独立的上下文。我曾经使用每个上下文的HttpSessionListener做过类似于您所要求的事情。关键在于,您需要拥有一个会话集合,该集合由根类加载器加载,而不是上下文类加载器。这是我的记忆方式:
创建一个类来保存每个上下文的活动会话。这个类必须位于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
您可以使用HttpSessionListener将会话的引用保存在数据结构中,然后随意使用它。

1

你看过Lamda探针吗?对于您的每个Web应用程序,您可以查看会话内容并将其全部过期。

alt text

如果你想自己编写应用程序来完成这个任务,Lamda Probe是开源的,所以你可以从他们那里获取代码来帮助实现你的目标。


看起来Lambda Probe已经被放弃了,但是有一个活跃的分支叫做Psi Probe - Roger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接