Java中的Session管理

5tmbdcev  于 4个月前  发布在  Java
关注(0)|答案(1)|浏览(52)

我试图在一个简单的Java应用程序中管理会话。我的想法是创建一个SessionManagerSingleton,它示例化会话和实际的Session,它包含真实的信息,如下所示:

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?我尝试使用全局变量,但这可能会在多用户应用程序中造成问题。(我知道它不是分布式应用程序,但我想这样管理它)。

plicqrtu

plicqrtu1#

根据注解,只有一个用户可以一次访问您的应用程序。在这种情况下,当用户登录时将当前活动会话的ID存储在全局变量中并在注销时擦除它是正确和合理的。
如果应用程序是并发访问的,我会先做一些修改:

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

字符串
由于初始化是在类加载时进行的,JVM保证每个类加载器只进行一次初始化,因此您不再需要担心同步或易失性。而且类将在第一次访问时加载,因此这已经是懒惰的了。对于边缘情况,您可以使用holder idiom

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


这样,许多线程(处理许多用户请求)可以安全地并发读取和更新Map。
说了这么多,你最初的问题仍然是:如何知道什么是 * 当前 * 会议?
通常,客户端有责任识别自己。例如,当用户通过(web/移动的/桌面)客户端应用程序,您将新生成的会话ID返回给客户端(可能在cookie中,或者自定义头中,或者只是在响应有效负载本身中)。(而不是您的服务器应用程序)然后将其存储在某个地方(浏览器可能将其存储在本地存储器或cookie中,移动的客户端可能将其存储在电话的共享首选项中,桌面客户端可能将其保存在某个地方的文件中),然后将其与后续的每个请求一起发送回应用程序。然后,您的应用程序可以使用客户端发送的ID并将正确的会话与每个请求关联起来。如果每个请求都由单独的专用线程提供服务,(与传统的Servlet模型一样),应用程序还可以将当前会话存储在ThreadLocal变量中,以使其可以从任何地方隐式访问(而不是将其作为每个方法的参数传递),并在请求结束时清理它。这通常由框架而不是应用程序本身处理。
如果你想模拟一个可并发访问的应用程序,你可以在用户登录时打印或显示新的会话ID,并要求将相同的ID传递给应用程序中的所有入口点,这会很麻烦,但这基本上是服务器应用程序真正要做的。
这有用吗

相关问题