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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3960711/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 04:10:04  来源:igfitidea点击:

How can I expire all my sessions in Tomcat?

javatomcatfitnesse

提问by Jean-Philippe Caruana

I would like to expire all my sessions in Tomcat. We test our product under Fitnesse and some sessions remain and the end of the session causes dependency between the tests. I do it by hand with the following code, but some sessions remain (I can check it with the http://localhost:8080/manager/html/listurl)

我想使我在 Tomcat 中的所有会话都过期。我们在 Fitnesse 下测试我们的产品,一些会话仍然存在,会话结束会导致测试之间存在依赖性。我使用以下代码手动完成,但仍有一些会话(我可以使用http://localhost:8080/manager/html/listurl检查它)

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);
}

Is there a way to do it more efficiently and immediate with no remaining session ?

有没有办法在没有剩余会话的情况下更有效和更直接地做到这一点?

采纳答案by Ricardo Marimon

I'm assuming your applications are really independent contexts. I have done something similar to what you are asking using an HttpSessionListenerfor every context. The tricky part here is that you need to have a Session Collection that is loaded by the root class loader as opposed to the context class loader. This is how I remember it:

我假设您的应用程序是真正独立的上下文。我已经做了一些类似于你在HttpSessionListener每个上下文中使用 an 的要求。这里的棘手部分是您需要有一个由根类加载器而不是上下文类加载器加载的会话集合。这是我记得它的方式:

Create a class which holds the active sessions for each context. This class mustreside in the tomcat /lib directory so that it becomes accessible by every context. It can't be part of any of the contexts.

创建一个类来保存每个上下文的活动会话。此类必须驻留在 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();
        }
      }
    }
  }

}

Create a listener for every context.

为每个上下文创建一个侦听器。

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());
      }
    }
  }

}

Registered each listener in the corresponding context's web.xml.

在相应上下文的web.xml.

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

You can then call the following line to invalidate everything from any context.

然后,您可以调用以下行来使任何上下文中的所有内容无效。

SessionMap.invalidate();

I'm synchronizing on the map just to be on the safe side.

我在地图上同步只是为了安全起见。

回答by Antonio

You could use HttpSessionListener to save the references to sessions in a data structure and then use it at your leisure

您可以使用 HttpSessionListener 将会话的引用保存在数据结构中,然后在闲暇时使用它

回答by Sean

Have you looked at Lamda Probe? For each of your web applications, you can view the contents of the session and expire them (all).

你看过Lamda Probe吗?对于您的每个 Web 应用程序,您都可以查看会话的内容并将它们(全部)过期。

alt text

替代文字

If you are keen on writing your own app to do this instead; Lamda Probe is open source, so you could take code from them to help accomplish your goal.

如果您热衷于编写自己的应用程序来执行此操作;Lamda Probe 是开源的,因此您可以从他们那里获取代码来帮助实现您的目标。