java – 如何在Tomcat中过期我的所有会话?

我想在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);
}

有没有办法更有效和更直接地执行,没有剩余的会话?

解决方法

我假设你的应用程序是真正独立的上下文.我已经做了类似于每个上下文使用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();

我在地图上进行同步,只是为了安全起见.

相关文章

应用场景 C端用户提交工单、工单创建完成之后、会发布一条工...
线程类,设置有一个公共资源 package cn.org.chris.concurre...
Java中的数字(带有0前缀和字符串)
在Java 9中使用JLink的目的是什么?
Java Stream API Filter(过滤器)
在Java中找到正数和负数数组元素的数量