我正在尝试在一个简单的 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 ? 我尝试使用全局变量,但这可能会在多用户应用程序中引起问题。 (我知道它不是分布式应用程序,但我想这样管理它)。
根据评论,只有一个用户可以一次访问您的应用程序。在这种情况下,它既正确又合理,因此只需在用户登录时将当前活动会话的 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
变量中,以使其可以从任何地方隐式访问(无需将其作为参数传递给每个请求)方法),并在请求结束时清理它。这通常由框架而不是应用程序本身处理。
这有帮助吗?