如何在Java中访问HTTP会话

时间:2010-07-13 09:53:07

标签: java session servlets

如何以优雅的方式通过id或Web应用程序(Java 2 EE)中所有当前活动的http会话获取任何http会话?

目前我有一个WebSessionListener,一旦创建了会话,我把它放在ConcurrentHashMap() (map.put(sessionId, sessionObj))中,一切正常,我可以随时通过会话ID从该地图检索HTTP会话,但它看起来像HttpSession个对象永远不会最终确定...即使会话无效,地图仍会引用无效的会话对象...此外,我已阅读this article,看起来WeakHashMap不可接受我的情况......

换句话说,我需要有可能查看任何HttpSession甚至获取所有当前活动的HttpSession并从那里检索一些属性......

请建议某人:)

更新

由于以下原因,我需要访问HttpSession对象:

有时用户会做一些可能影响另一个并发用户工作的操作/请求,例如管理员应禁用用户帐户,但此用户当前正在使用该系统,在这种情况下,我需要向管理员显示一条消息,例如: “用户XXX目前正在使用该系统”因此我需要检查是否有任何持有用户XXX凭据的HttpSession已经存在且处于活动状态。所以这就是我需要这样的可能性来获得任何http会话甚至所有会话。

我当前的实现是:SessionManager,它知道所有会话(ConcurrentMap)和HttpSessionListener,它们将会话放入/删除SessionManager。

我担心可能出现的内存问题,我想与某人讨论这个问题,但目前我清楚地看到一切都应该正常工作,因为当调用sessionDestroyed()方法时,所有无效的会话都将从地图中删除。 ..

非常感谢您的重播,但现在我明白这个问题只是想象力了:))

3 个答案:

答案 0 :(得分:7)

根据您的澄清:

  

有时用户会做一些可能影响另一个并发用户工作的操作/请求,例如管理员应该禁用用户帐户但该用户当前正在使用该系统,在这种情况下我需要向管理员显示一条消息例如“用户XXX目前正在使用该系统”因此我需要检查是否有任何持有用户XXX凭据的HttpSession已经存在且处于活动状态。所以这就是我需要这样的可能性来获得任何http会话甚至所有会话。

为此,您实际上不需要了解会话的任何信息。您只需要知道哪些用户已登录。为此,您可以完美地让代表登录用户的模型对象实现HttpSessionBindingListener。我当然假设你通过设置/删除User模型作为会话属性来遵循登录/注销用户的正常习惯。

public class User implements HttpSessionBindingListener {

    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        Set<User> logins = (Set<User>) event.getSession().getServletContext().getAttribute("logins");
        logins.add(this);
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        Set<User> logins = (Set<User>) event.getSession().getServletContext().getAttribute("logins");
        logins.remove(this);
    }

    // @Override equals() and hashCode() as well!

}

然后在您的管理应用中的某处,只需从ServletContext获取登录信息:

Set<User> logins = (Set<User>) servletContext.getAttribute("logins");

答案 1 :(得分:5)

一般来说,您的servlet容器将拥有自己的会话管理器,它负责维护会话的生命周期,并将传入的请求与适当的会话相关联(通过cookie,锚参数,无论其想要的策略)。 / p>

执行此操作的优雅方法是以任何允许的方式挂钩此会话管理器。例如,您可以子类化默认值,以允许您访问任意会话。

然而,听起来你正在做的事情掩盖了你的架构的潜在问题。会话中包含的数据应该特定于该会话,因此通常您不需要查找任意数据以提供Web应用程序的标准逻辑。管理/内务处理任务通常由容器处理 - 所以再次,你不应该干涉这个。

如果您指示了为什么您想要访问任意会话,那么替代方法可能更适合您的目标。

答案 2 :(得分:4)

Andrzej Doyle是对的。但如果您真的想要管理自己的会话列表,那么连接到您的容器的方式是通过HttpSessionListener - example code

每当创建一个新会话时都会调用侦听器,更重要的是,在会话被销毁时也会调用它。这将允许您模仿容器的会话簿记。

您使用web.xml将会话侦听器注册为您应用的生命周期监听器。

您可以使用ServletContext将会话列表与容器中的其他进程进行通信,或者您可以使用例如以下方法制作更脏的方案。静态类字段。