我试图在一个简单的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?我尝试使用全局变量,但这可能会在多用户应用程序中造成问题。(我知道它不是分布式应用程序,但我想这样管理它)。
1条答案
按热度按时间plicqrtu1#
根据注解,只有一个用户可以一次访问您的应用程序。在这种情况下,当用户登录时将当前活动会话的ID存储在全局变量中并在注销时擦除它是正确和合理的。
如果应用程序是并发访问的,我会先做一些修改:
字符串
由于初始化是在类加载时进行的,JVM保证每个类加载器只进行一次初始化,因此您不再需要担心同步或易失性。而且类将在第一次访问时加载,因此这已经是懒惰的了。对于边缘情况,您可以使用holder idiom。
型
这样,许多线程(处理许多用户请求)可以安全地并发读取和更新Map。
说了这么多,你最初的问题仍然是:如何知道什么是 * 当前 * 会议?
通常,客户端有责任识别自己。例如,当用户通过(web/移动的/桌面)客户端应用程序,您将新生成的会话ID返回给客户端(可能在cookie中,或者自定义头中,或者只是在响应有效负载本身中)。(而不是您的服务器应用程序)然后将其存储在某个地方(浏览器可能将其存储在本地存储器或cookie中,移动的客户端可能将其存储在电话的共享首选项中,桌面客户端可能将其保存在某个地方的文件中),然后将其与后续的每个请求一起发送回应用程序。然后,您的应用程序可以使用客户端发送的ID并将正确的会话与每个请求关联起来。如果每个请求都由单独的专用线程提供服务,(与传统的Servlet模型一样),应用程序还可以将当前会话存储在
ThreadLocal
变量中,以使其可以从任何地方隐式访问(而不是将其作为每个方法的参数传递),并在请求结束时清理它。这通常由框架而不是应用程序本身处理。如果你想模拟一个可并发访问的应用程序,你可以在用户登录时打印或显示新的会话ID,并要求将相同的ID传递给应用程序中的所有入口点,这会很麻烦,但这基本上是服务器应用程序真正要做的。
这有用吗