Java 中的会话管理

问题描述 投票:0回答:1

我正在尝试在一个简单的 Java 应用程序中管理会话。我的想法是创建一个 SessionManagerSingleton 来实例化会话和实际会话,其中保存真实信息,如下所示:

public class SessionManagerSingleton {
    private static SessionManagerSingleton instance;
    private Map<String, Session> activeSessions;

    private SessionManagerSingleton() {
        activeSessions = new HashMap<>();
    }

    public static synchronized SessionManagerSingleton getInstance() {
        if (instance == null) {
            instance = new SessionManagerSingleton();
        }
        return instance;
    }

    public String addSession(String email) {
        String sessionId = generateSessionId();
        Session session = new Session(email);
        activeSessions.put(sessionId, session);
        return sessionId;
    }

    public Session getSession(String sessionId) {
        return activeSessions.get(sessionId);
    }
    private String generateSessionId() {
        return UUID.randomUUID().toString();
    }
}


package com.example.wanderwisep.sessionManagement;
import java.util.UUID;
public class Session {
    String email;
    //Other Information
    String id;
    public Session(String email) {
        id = generateSessionId();
        this.email = email;
    }
    private String generateSessionId() {
        String id = UUID.randomUUID().toString();
        System.out.println("id sessione:");
        System.out.println(id);
        return id;
    }

我的问题是,如何在代码的另一部分保存调用 getSession(String id) 的 id ? 我尝试使用全局变量,但这可能会在多用户应用程序中引起问题。 (我知道它不是分布式应用程序,但我想这样管理它)。

java authentication session singleton logout
1个回答
0
投票

根据评论,只有一个用户可以一次访问您的应用程序。在这种情况下,它既正确又合理,因此只需在用户登录时将当前活动会话的 ID 存储在全局变量中,并在注销时将其擦除即可。

如果应用程序可以同时访问,我会进行一些更改:

  • 初始化单例内联:
private static SessionManagerSingleton instance = new SessionManagerSingleton();
   
public static SessionManagerSingleton getInstance() {
    return instance;
}

由于初始化在类加载时发生,并且 JVM 保证每个类加载器发生一次,因此您不再需要担心同步或波动性。无论如何,该类都会在第一次访问时加载,因此这已经是它需要的惰性了。对于边缘情况,您可以使用 holder 习惯用法;

  • 使活动会话映射线程安全:
private SessionManagerSingleton() {
    activeSessions = new ConcurrentHashMap<>();
}

这样,许多线程可以安全地同时读取和更新地图。

尽管如此,您最初的问题仍然是:如何知道什么是当前会话?

通常情况下,客户有责任表明自己的身份。例如。当用户通过(Web/移动/桌面)客户端应用程序登录时,您将新生成的会话 ID 返回给客户端(可能在 cookie 中,或自定义标头中,或仅在响应负载本身中)。然后,客户端将其存储在某处(浏览器可能将其存储在本地存储或其 cookie 中,移动客户端可能将其存储在手机的共享首选项中,桌面客户端可能将其保存为文件),然后将其发送回对应用程序的每个后续请求。然后,您的应用程序可以使用客户端发送的 ID,并将正确的会话与每个请求相关联。如果每个请求都由单独的专用线程提供服务(如在传统的 Servlet 模型中),则应用程序还可以将当前会话存储在

ThreadLocal
变量中,以使其可以从任何地方隐式访问(无需将其作为参数传递给每个请求)方法),并在请求结束时清理它。这通常由框架而不是应用程序本身处理。

这有帮助吗?

© www.soinside.com 2019 - 2024. All rights reserved.