2010-10-18 18 views
10

Mi piacerebbe scadere tutte le mie sessioni in Tomcat. Testiamo il nostro prodotto sotto Fitnesse e alcune sessioni rimangono e la fine della sessione causa dipendenza tra i test. Io lo faccio a mano con il seguente codice, ma alcune sessioni rimango (posso controllare con il http://localhost:8080/manager/html/list URL)Come posso scadere tutte le mie sessioni in 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); 
} 

C'è un modo per farlo in modo più efficiente ed immediato con nessuna sessione restante?

risposta

7

Sto assumendo che le tue applicazioni siano in contesti davvero indipendenti. Ho fatto qualcosa di simile a quello che stai chiedendo usando un HttpSessionListener per ogni contesto. La parte difficile è che è necessario disporre di una raccolta sessione che viene caricata dal caricatore della classe radice anziché dal caricatore della classe di contesto. Ecco come lo ricordo:

Creare una classe che contiene le sessioni attive per ogni contesto. Questa classe deve essere risiedere nella directory tomcat/lib in modo che diventi accessibile da ogni contesto. Non può far parte di nessuno dei contesti.

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

} 

Creare un listener per ogni contesto.

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

} 

Registrato ogni ascoltatore nel corrispondente contesto del web.xml.

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

È quindi possibile chiamare la seguente riga per invalidare tutto da qualsiasi contesto.

SessionMap.invalidate(); 

Mi sto sincronizzando sulla mappa solo per essere al sicuro.

+0

Class SessionMap non è thread-safe –

3

Si potrebbe utilizzare HttpSessionListener per salvare i riferimenti a sedute in una struttura di dati e poi usarlo a vostro piacimento

1

Hai guardato Lamda Probe? Per ciascuna delle tue applicazioni Web, puoi visualizzare i contenuti della sessione e scadere (tutti).

alt text

Se siete appassionati di scrivere il proprio app per fare questo, invece; Lamda Probe è open source, quindi puoi prendere il codice da loro per aiutarti a raggiungere il tuo obiettivo.

+0

Sembra che Lambda Probe sia abandonware ma è presente un fork attivo chiamato [Psi Probe] (https://psi-probe.github.io/psi-probe/). – Roger

Problemi correlati