Digamos que tengo una aplicación web en ejecución con 0 o más objetos válidos HttpSession
asociados. Quiero una forma de acceder a la lista actual de objetos válidos HttpSession
. 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.¿Cómo obtengo una lista de todos los objetos HttpSession en una aplicación web?
Antes de empezar a hornear mi propia solución que pensé que debería hacer la pregunta:
¿La API de servlets proporcionan unos medios de conseguir el acceso a la lista completa de los objetos no invalida la sesión?
Estoy utilizando Tomcat 6.x como contenedor de aplicaciones web y la biblioteca MyFaces 1.2.x (JSF).
SOLUCIÓN
he seguido un enfoque similar a lo que se discutió en BalusC estas preguntas existentes:
- How to easily implement "who is online" in Grails or Java Application ?
- JSF: How to invalidate an user session when he logs twice with the same credentials
he modificado por SessionData
clase 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 de nuevo, 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 HttpSession
, por lo que no tengo la oportunidad de volver a poner correctamente 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 consiste en comparar el tiempo de creación 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, entonces llamo al invalidate()
y el usuario es 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 desde el método contextInitialized()
de mi escucha.
Mi solicitud tendrá un número limitado de usuarios en una red privada, por lo que no necesitaré la implementación distribuida. Aunque estoy de acuerdo con tu comentario. –
Supongo que la forma de enmendar esto (así como también la persistencia en disco persiguiendo) sería hacer que el oyente actualice un almacén de datos compartido (Redis, Memcached o algo así) que realiza un seguimiento de las sesiones. – Thilo