【问题标题】:Servlet, how to manage "per user" singleton accessorsServlet,如何管理“每个用户”单例访问器
【发布时间】:2014-10-13 19:01:06
【问题描述】:

我正在使用一个 servlet,在其中我需要为每个用户创建一个对象实例,通常我会使用单例来执行此操作,但因为(据我所知)servlet 本身作为单例工作我是有点迷茫:

我怎样才能为每个会话/用户准确地生成一个实例? 我如何确定它会在会话超时时被销毁?

最好的方法是什么,等待 HttpServlet 的某些事件或对访问某些属性的请求采取行动以了解正在调用的会话?

编辑: 实际场景是一个使用外部组件进行数据访问的 Web 应用程序,这个对象对数据检索的作用并不有趣,可能是数据库访问或 Web 服务调用,我可以忽略它。 我必须为每个 Httpsession 创建一个该对象的实例,并确保它在会话过期时间后被销毁。

编辑

似乎 HttpSessionListener 可能是一个解决方案:我可以创建我的对象,在创建会话时将其在 Map 中与 sessionid 相关联,并在会话到期时销毁。有人有这方面的经验吗?

【问题讨论】:

  • 线程怎么样?你试过了吗?
  • Sorry Ashes 但我从来没有使用过“线程”这个词会话
  • 为每个用户维护一个会话 ID?会话范围:每个页面/每个浏览器/每个应用程序?
  • 不废话,我们说的是创建一个特定类的实例,我们为每个 HTTPSession 称它为 Foo

标签: java servlets


【解决方案1】:

对于简单的情况,您可以使用HttpSessionListener,如下所示:

@WebListener
public class MySessionListener implements HttpSessionListener {
    public void sessionCreated(HttpSessionEvent se) {
        // new session created - add your singleton
        Foo f = new Foo();
        se.getSession().setAttribute("Foo", f);
        // if you need id you can use - se.getSession().getId();
    }

    public void sessionDestroyed(HttpSessionEvent se) {
        // session destroyed - do cleanup
        Foo f = (Foo) se.getSession().getAttribute("Foo");
        f.destroy(); // your object cleanup method
    }
}

如果您需要使用会话复制在集群中运行它,您的类应该很小并且Serializable,否则您需要实现您的 Map 解决方案和HttpSessionActivationListener 以在其他 JVM 上恢复其状态。

【讨论】:

  • 这或多或少是我已经做过的,我创建了一个包含地图的单例类,在创建的会话中添加实例并在会话被破坏时删除,我猜是因为我正在使用一个带地图的单例我不需要像 httpsessionactivationlistener 那样实现其他部分,我只是使用 sessionid 作为键来维护关系
  • @user1274347 如果您计划进行会话复制,您将需要 httpsessionactivationlistener,因为如果会话将移动到其他 JVM,则该 JVM 中将没有您的对象实例用于激活会话。当然,您也可以在第一次访问时将实例初始化为惰性。
  • 是的,实际上我目前只是在第一次使用时创建实例并在会话到期时将其销毁,说我在会话创建时创建它是一种简化。谢谢你的建议
【解决方案2】:

不确定您到底在做什么,但最简单的方法是为每个启动的会话创建一个客户端 cookie。

cookie 本身可以有一个到期期限,您可以跟踪每个会话的服务器跟踪,其中密钥是生成的 cookie。

一旦客户端有一个cookie,他就会在每个请求中使用它,以便保持在同一个会话中。

当然,您需要一种方法让每个用户登录并分配他的 cookie,以及一些服务器逻辑来删除未使用的会话......等等。

【讨论】:

  • 我认为 cookie 不是我的解决方案,我需要为每个会话创建一个特定类的实例。我添加了一些更新问题的细节
【解决方案3】:

简单的解决方案:

在下面的描述中,Blammy 是每个会话的对象名称

  1. 在登录或会​​话创建期间,将 Blammy 对象添加到会话。如果没有会话,HttpServletRequest.getSession(false) 将返回 null。这意味着您需要 a) 创建一个会话 b) 将 Blammy 添加到新会话中。
  2. 登录后,检查 Blammy 对象的会话。如果没有 Blammy,请做出适当的反应
  3. 在会话中酌情使用 Blammy 对象。

【讨论】:

  • 有些东西我不明白:1)我在没有会话的情况下采取行动怎么可能存在?我们正在谈论一个 servlet 2) 如何处理会话创建和会话销毁?
  • 简短回答:阅读 servlet 教程。会话创建不是自动的。使用 HttpSessionListener 对会话创建和会话销毁事件做出反应。
【解决方案4】:

您可以使用 HttpSessionEvent。在创建会话时,添加一个带有常量键的会话属性,并将您的对象实例作为值。

【讨论】:

    猜你喜欢
    • 2011-08-14
    • 2016-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    • 2014-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多