Java 如何获取 Web 应用程序中所有 HttpSession 对象的列表?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3771103/
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
How do I get a list of all HttpSession objects in a web application?
提问by Jim Tough
Let's say I have a running Java-based web application with 0 or more valid HttpSession
objects associated with it. I want a way to access the current list of valid HttpSession
objects. I was thinking that I could implement an HttpSessionListener
and use it to append to a list of session id values that are stored in an application-scoped attribute, but then I'm on the hook to update the list as sessions are invalidated and who knows what else.
假设我有一个正在运行的基于 Java 的 Web 应用程序,其中有 0 个或多个HttpSession
与之关联的有效对象。我想要一种访问当前有效HttpSession
对象列表的方法。我在想我可以实现一个HttpSessionListener
并使用它来附加到存储在应用程序范围属性中的会话 id 值列表,但随后我需要更新列表,因为会话无效并且谁知道是什么别的。
Before I start baking my own solution I thought I should ask the question:
Does the servlet API provide some means of getting access to the complete list of non-invalidated session objects?
在我开始构建自己的解决方案之前,我想我应该问一个问题:
servlet API 是否提供了某种方法来访问非无效会话对象的完整列表?
I am using Tomcat 6.x as my web application container, and the MyFaces 1.2.x (JSF) library.
我使用 Tomcat 6.x 作为我的 Web 应用程序容器和 MyFaces 1.2.x (JSF) 库。
SOLUTION
I followed an approach similar to what BalusC discussed in these existing questions:
解决方案
我采用了类似于 BalusC 在这些现有问题中讨论的方法:
- 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
I modified by SessionData
class to implement HttpSessionBindingListener
. When a binding event happens, the object will either add or remove itself from the set of all the SessionData
objects.
我按SessionData
类修改以实现HttpSessionBindingListener
. 当绑定事件发生时,该对象将从所有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);
}
}
The one thing that continues to irritate me is what happens when Tomcat is restarted. Unless Tomcat has been properly configured to NOT serialize sessions to disk, it will do so. When Tomcat starts up again, the HttpSession
objects (and the SessionData
objects along with them) are deserialized and the sessions are made valid again. However, the serialization/deserialization totally sidesteps the HttpSession
listener events, so I do not have the opportunity to gracefully put the deserialized reference to the SessionData
back in my managed Set of objects after the restart.
继续激怒我的一件事是重新启动 Tomcat 时会发生什么。除非 Tomcat 已正确配置为不将会话序列化到磁盘,否则它会这样做。当 Tomcat 再次启动时,HttpSession
对象(SessionData
以及与它们一起的对象)被反序列化并且会话再次有效。但是,序列化/反序列化完全避开了HttpSession
侦听器事件,因此我没有机会SessionData
在重新启动后优雅地将反序列化的引用放在我的托管对象集中后面。
I don't have any control over the production configuration of Tomcat in my customer's organization, so I cannot assume that it will be done the way I expect it.
我对客户组织中 Tomcat 的生产配置没有任何控制权,所以我不能假设它会按照我期望的方式完成。
My workaround is to compare the HttpSession
creation time with the application startup time when a request is received. If the session was created before the application startup time, then I call invalidate()
and the user is sent to an error/warning page with an explanation of what happened.
我的解决方法是在HttpSession
收到请求时将创建时间与应用程序启动时间进行比较。如果会话是在应用程序启动时间之前创建的,那么我会调用invalidate()
并将用户发送到错误/警告页面,并解释所发生的情况。
I get the application startup time by implementing a ServletContextListener
and storing the current time inside an application-scoped object from within the contextInitialized()
method of my listener.
我通过实现 aServletContextListener
并将当前时间存储在contextInitialized()
我的侦听器方法中的应用程序范围对象中来获取应用程序启动时间。
采纳答案by BalusC
No, the Servlet API doesn't provide a way. You really have to get hold of them all with help of a HttpSessionListener
. You can find several examples in the following answers:
不,Servlet API 没有提供方法。您真的必须借助HttpSessionListener
. 您可以在以下答案中找到几个示例:
回答by gertas
There is no straight forward way. It depends on deployment. Above will fail once you decide to introduce distributed deployment and load balancing.
没有直接的方法。这取决于部署。一旦您决定引入分布式部署和负载平衡,上述操作就会失败。
回答by Nathan Crause
Not really an answer, but in the good ol' days there was "javax.servlet.http.HttpSessionContext", but it was dropped as of version 2.1, explicitly with no replacement: https://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpSessionContext.html
不是真正的答案,但在过去的好日子里有“javax.servlet.http.HttpSessionContext”,但它从 2.1 版开始被删除,明确没有替代:https: //tomcat.apache.org/tomcat- 5.5-doc/servletapi/javax/servlet/http/HttpSessionContext.html