2010-10-18 10 views
10

Me gustaría caducar todas mis sesiones en Tomcat. Probamos nuestro producto bajo Fitnesse y algunas sesiones permanecen y el final de la sesión causa dependencia entre las pruebas. Lo hago a mano con el siguiente código, pero se mantienen algunas sesiones (puedo comprobar con el http://localhost:8080/manager/html/list url)¿Cómo puedo caducar todas mis sesiones en Tomcat?

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

¿Hay una manera de hacerlo más eficiente e inmediata con ninguna sesión restante?

Respuesta

7

Supongo que sus aplicaciones son contextos realmente independientes. He hecho algo similar a lo que está pidiendo usando un HttpSessionListener para cada contexto. La parte difícil aquí es que debe tener una Colección de sesión cargada por el cargador de clases de raíz en lugar del cargador de clases de contexto. Así es como lo recuerdo:

Crea una clase que contiene las sesiones activas para cada contexto. Esta clase debe residir en el directorio tomcat/lib para que sea accesible en todos los contextos. No puede ser parte de ninguno de los contextos.

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

} 

Crea un oyente para cada contexto.

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

} 

Registrado cada oyente en el contexto correspondiente de web.xml.

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

A continuación, puede llamar a la siguiente línea para invalidar todo, desde cualquier contexto.

SessionMap.invalidate(); 

Estoy sincronizando en el mapa sólo para estar seguro.

+0

Class SessionMap no es seguro para subprocesos –

3

Usted podría utilizar HttpSessionListener para salvar las referencias a las sesiones en una estructura de datos y luego usarlo en su tiempo libre

1

¿Has mirado en Lamda Probe? Para cada una de sus aplicaciones web, puede ver los contenidos de la sesión y caducarlos (todos).

alt text

Si usted está interesado en escribir su propia aplicación para hacer esto en su lugar; Lamda Probe es de código abierto, por lo que puede tomar el código de ellos para ayudar a lograr su objetivo.

+0

Parece que Lambda Probe es abandonware pero hay un fork activo llamado [Psi Probe] (https://psi-probe.github.io/psi-probe/). – Roger

Cuestiones relacionadas