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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 04:44:05  来源:igfitidea点击:

How do I get a list of all HttpSession objects in a web application?

javaweb-applicationsservletshttpsession

提问by Jim Tough

Let's say I have a running Java-based web application with 0 or more valid HttpSessionobjects associated with it. I want a way to access the current list of valid HttpSessionobjects. I was thinking that I could implement an HttpSessionListenerand 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 在这些现有问题中讨论的方法:

I modified by SessionDataclass to implement HttpSessionBindingListener. When a binding event happens, the object will either add or remove itself from the set of all the SessionDataobjects.

我按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 HttpSessionobjects (and the SessionDataobjects along with them) are deserialized and the sessions are made valid again. However, the serialization/deserialization totally sidesteps the HttpSessionlistener events, so I do not have the opportunity to gracefully put the deserialized reference to the SessionDataback 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 HttpSessioncreation 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 ServletContextListenerand 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