java - sesiones - ¿Cómo obtengo una lista de todos los objetos HttpSession en una aplicación web?
manejo de sesiones en spring mvc (3)
No hay una manera directa. Depende de la implementación. Más arriba fallará una vez que decida introducir implementación distribuida y balanceo de carga.
Supongamos que tengo una aplicación web en ejecución con 0 o más objetos HttpSession
válidos asociados. Quiero una forma de acceder a la lista actual de objetos HttpSession
válidos. Estaba pensando que podría implementar un HttpSessionListener
y usarlo para anexar a una lista de valores de id de sesión que están almacenados en un atributo con ámbito de aplicación, pero luego estoy al acecho para actualizar la lista ya que las sesiones se invalidan y quién sabe Qué más.
Antes de comenzar a preparar mi propia solución, pensé que debería hacer la pregunta:
¿La API de servlet proporciona algunos medios para obtener acceso a la lista completa de objetos de sesión no invalidados?
Estoy usando Tomcat 6.x como mi contenedor de aplicaciones web y la biblioteca MyFaces 1.2.x (JSF).
SOLUCIÓN
Seguí un enfoque similar al que BalusC discutió en estas preguntas existentes:
- ¿Cómo implementar fácilmente "quién está en línea" en la aplicación Grails o Java?
- JSF: cómo invalidar una sesión de usuario cuando registra dos veces con las mismas credenciales
SessionData
por clase SessionData
para implementar HttpSessionBindingListener
. Cuando ocurre un evento vinculante, el objeto se agregará o eliminará del conjunto de todos los objetos SessionData
.
@Override
public void valueBound(HttpSessionBindingEvent event) {
// Get my custom application-scoped attribute
ApplicationData applicationData = getApplicationData();
// Get the set of all SessionData objects and add myself to it
Set<SessionData> activeSessions = applicationData.getActiveSessions();
if (!activeSessions.contains(this)) {
activeSessions.add(this);
}
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
HttpSession session = event.getSession();
ApplicationData applicationData = getApplicationData();
Set<SessionData> activeSessions = applicationData.getActiveSessions();
if (activeSessions.contains(this)) {
activeSessions.remove(this);
}
}
Lo único que continúa irritándome es lo que sucede cuando se reinicia Tomcat. A menos que Tomcat se haya configurado correctamente para NO serializar sesiones en el disco, lo hará. Cuando Tomcat se inicia nuevamente, los objetos HttpSession
(y los objetos SessionData
junto con ellos) se deserializan y las sesiones vuelven a ser válidas. Sin embargo, la serialización / deserialización evita totalmente los eventos de escucha de HttpSession
, por lo que no tengo la oportunidad de volver a poner la referencia deserializada en SessionData
en mi Conjunto de objetos administrado después del reinicio.
No tengo ningún control sobre la configuración de producción de Tomcat en la organización de mi cliente, por lo que no puedo suponer que se hará de la manera que lo esperaba.
Mi solución es comparar el tiempo de creación de HttpSession
con el tiempo de inicio de la aplicación cuando se recibe una solicitud. Si la sesión se creó antes del tiempo de inicio de la aplicación, llamé a invalidate()
y el usuario fue enviado a una página de error / advertencia con una explicación de lo sucedido.
Obtengo el tiempo de inicio de la aplicación implementando un ServletContextListener
y almacenando la hora actual dentro de un objeto con ámbito de aplicación dentro del método contextInitialized()
de mi escucha.
No, la API de Servlet no proporciona una forma. Realmente tiene que hacerse con todos ellos con la ayuda de un HttpSessionListener
. Puede encontrar varios ejemplos en las siguientes respuestas:
Realmente no era una respuesta, pero en los buenos viejos tiempos había "javax.servlet.http.HttpSessionContext", pero se eliminó a partir de la versión 2.1, explícitamente sin reemplazo: https://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpSessionContext.html