如何重新连接到现有的JavaEE会话

如何重新连接到现有的JavaEE会话,java,jakarta-ee,Java,Jakarta Ee,当有人向我的应用程序发出servlet请求时,就会创建一个会话。我正在为此连接创建唯一ID并将其返回给客户端 当客户端返回该唯一ID时,我希望将它们重新连接到其现有会话,而不管jsessionid附带了什么 想法?这是应用程序/web容器的工作。默认情况下,应用程序/web容器关联所需的会话。我认为容器不会提供可用于查找会话的API 您的用例表明您不希望应用程序/web容器创建会话,而是希望自己管理会话。在这种情况下,从app/web容器的角度来看,每个请求都是无状态的。您可以使用映射(如果是集

当有人向我的应用程序发出servlet请求时,就会创建一个会话。我正在为此连接创建唯一ID并将其返回给客户端

当客户端返回该唯一ID时,我希望将它们重新连接到其现有会话,而不管jsessionid附带了什么


想法?

这是应用程序/web容器的工作。默认情况下,应用程序/web容器关联所需的会话。我认为容器不会提供可用于查找会话的API


您的用例表明您不希望应用程序/web容器创建会话,而是希望自己管理会话。在这种情况下,从app/web容器的角度来看,每个请求都是无状态的。您可以使用映射(如果是集群环境,则为分布式映射)自行管理会话。你会有很多东西需要管理,安全性,持久性,超时等等

这是应用程序/web容器的工作。默认情况下,应用程序/web容器关联所需的会话。我认为容器不会提供可用于查找会话的API


您的用例表明您不希望应用程序/web容器创建会话,而是希望自己管理会话。在这种情况下,从app/web容器的角度来看,每个请求都是无状态的。您可以使用映射(如果是集群环境,则为分布式映射)自行管理会话。你会有很多东西需要管理,安全性,持久性,超时等等

使用会话对象获取会话id

拿张地图,树地图。SessionId是键,uniqueId是值

对于检查前的每个请求,映射包含SessionId,如果不存在,则将键值放入映射中

确保您使用的树映射是静态的

最后,在使会话无效时,从树映射中删除密钥


使用TreeMap的原因是它不允许空值。因此,即使错误地插入空值,但如果性能有问题,请使用HashMap,它比TreeMap更好。

使用session对象获取会话id

拿张地图,树地图。SessionId是键,uniqueId是值

对于检查前的每个请求,映射包含SessionId,如果不存在,则将键值放入映射中

确保您使用的树映射是静态的

最后,在使会话无效时,从树映射中删除密钥


使用TreeMap的原因是它不允许空值。因此,即使错误地插入空值,但如果性能有问题,请使用HashMap,它比TreeMap更好。

我假设服务器上的现有会话在收到请求之前超时,而不是因为用户注销

由于会话将被删除,其数据将丢失,因此您必须复制会话数据以允许自动“会话继续”

注意未经测试的代码,只是一个想法

我们的想法是监视
HttpSessionListener.sessionDestroyed()
事件:

class SessionDataBackupListener implements HttpSessionListener {
    private Map<String,Object> oldSessions = new HashMap<String,Object>();

    public void sessionDestroyed(HttpSessionEvent event) {
      final Session s = event.getSession();
      if (s.getAttribute("logOut")) {
        // Session was closed on-command, nothing to do.
        return;
      }

      // Session (probably) timed-out.
      Object sessionData = extractSessionData(s);

      // This should go into some kind of singleton DAO object.
      oldSessions.put(s.getAttribute("uniqueId"), sessionData);
    }
}
您的登录处理程序如下所示:

  public void logOut(HttpServletRequest req) {
    final Session s = req.getSession();
    final String userId = s.getParameter("userId");
    // Log the user out.

    // Mark the session was closed on-command.
    s.setAttribute("logOut", Boolean.TRUE);
  }
  public void logIn(HttpServletRequest req) {
    final String uniqueId = s.getParameter("uniqueId");
    Session s = req.getSession(false);

    // User returning after time-out?
    if (s == null && uniqueId != null) {
      // Create new session...
      s = req.getSession(true);

      // ...assign it the same uniqueId...
      s.setAttribute("uniqueId", uniqueId);

      // ...and put back old session data.
      copyDataToSession(s, getOldSessionData(uniqueId));
    }
    else {
      // User logging in as usual.
    }
  }

getOldSessionData(最终字符串uniqueId)
将查找早期会话的singleton DAO对象。

我假设服务器上现有会话在收到请求之前超时,而不是因为用户注销

由于会话将被删除,其数据将丢失,因此您必须复制会话数据以允许自动“会话继续”

注意未经测试的代码,只是一个想法

我们的想法是监视
HttpSessionListener.sessionDestroyed()
事件:

class SessionDataBackupListener implements HttpSessionListener {
    private Map<String,Object> oldSessions = new HashMap<String,Object>();

    public void sessionDestroyed(HttpSessionEvent event) {
      final Session s = event.getSession();
      if (s.getAttribute("logOut")) {
        // Session was closed on-command, nothing to do.
        return;
      }

      // Session (probably) timed-out.
      Object sessionData = extractSessionData(s);

      // This should go into some kind of singleton DAO object.
      oldSessions.put(s.getAttribute("uniqueId"), sessionData);
    }
}
您的登录处理程序如下所示:

  public void logOut(HttpServletRequest req) {
    final Session s = req.getSession();
    final String userId = s.getParameter("userId");
    // Log the user out.

    // Mark the session was closed on-command.
    s.setAttribute("logOut", Boolean.TRUE);
  }
  public void logIn(HttpServletRequest req) {
    final String uniqueId = s.getParameter("uniqueId");
    Session s = req.getSession(false);

    // User returning after time-out?
    if (s == null && uniqueId != null) {
      // Create new session...
      s = req.getSession(true);

      // ...assign it the same uniqueId...
      s.setAttribute("uniqueId", uniqueId);

      // ...and put back old session data.
      copyDataToSession(s, getOldSessionData(uniqueId));
    }
    else {
      // User logging in as usual.
    }
  }

getOldSessionData(最终字符串uniqueId)
将查找早期会话的singleton DAO对象。

不确定您的实际需求是什么,但在我看来,您似乎希望控制会话id,而不依赖于生成的容器
jsessionid

对我来说,最简单的解决方案是自定义应用程序服务器/Web容器使用的会话标识符。所有服务器都提供此功能,因此基本上我将以以下方式实现它:

  • 如果您不喜欢
    jsessionid
    ,请自定义服务器,以便为会话标识参数使用所需的名称

  • 创建会话自定义会话存储库或管理器,用于管理容器的会话。此步骤将特定于您的服务器,基本上您要确保所有服务器实例都使用一个中央存储库,在该存储库中它们需要查找/更新会话。这将负责多服务器部署,而不需要基于粘性会话的负载平衡

  • 将创建/更新/重新附加/删除会话的工作留在容器中。它就是为了做到这一点

  • 现在,如果您认为这看起来像很多配置,并且非常特定于容器,那么我同意您的看法。但我也认为重复已经存在的功能(干式)是没有意义的

    如果我读了你的问题并尝试将其分解为功能,那么基本上就是服务器处理Http会话的方式,使用一个已识别的传统名称
    jsessionid
    。因此,定制现有功能感觉像是一个自然的解决方案


    希望这有帮助。如果我误解了您的问题,请务必让我知道。

    不确定您的真正需求是什么,但在我看来,您似乎希望控制会话id,而不是依赖生成的容器
    jsessionid

    对我来说,最简单的解决方案是自定义应用程序服务器/Web容器使用的会话标识符。