当有人对我的应用程序发出servlet请求时,会创建一个会话。我正在为此连接创建一个唯一的ID并将其返回给客户端。
当客户端返回该唯一ID时,我想将它们重新附加到现有会话,而不管jsessionid的内容是什么。
想法?
答案 0 :(得分:5)
这是应用程序/ Web容器的工作。默认情况下,应用程序/ Web容器关联所需的会话。我认为容器不会提供可用于查找会话的API。
您的用例表明您不希望app / web容器创建会话,而您希望自己管理它。在这种情况下,每个请求都是app / web容器视角下的无状态请求。您可以使用映射(如果是集群环境,则为分布式映射)为自己管理会话。你将拥有很多东西来管理,安全性,持久性,超时等等。
答案 1 :(得分:0)
使用Session对象获取会话ID。
拍摄地图,TreeMap。 SessionId将是关键,您的uniqueId将是值。
对于检查前的每个请求,地图包含SessionId,如果不存在,则将键值放入地图中。
确保您使用的TreeMap是静态的。
最后,当您使会话无效时,从TreeMap中删除密钥。
使用TreeMap的原因是因为它不允许空值。因此即使错误地你也不能插入空值,但是如果性能是个问题,请使用HashMap,与TreeMap相比更好。
答案 2 :(得分:0)
我假设在收到请求之前服务器上的现有会话超时,而不是因为用户已注销。
由于会话将被删除并且其数据丢失,您必须复制会话数据以允许自动“会话继续”。
注意未经测试的代码,只是一个想法。
我们的想法是关注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(final String uniqueId)
会在早期会话中查找单例DAO对象。
答案 3 :(得分:0)
不确定您的实际要求是什么,但在我看来,您似乎想要控制会话ID,而不是依赖于生成的容器jsessionid
。
对我来说,最简单的解决方案是自定义Application Server / Web容器使用的会话标识符。所有服务器都提供这种功能,所以基本上我会用以下方式实现它:
如果您不喜欢jsessionid
,请自定义您的服务器以使用您想要的会话识别参数名称。
创建会话自定义会话存储库或管理器,它将管理容器的会话。此步骤将特定于您的服务器,基本上您确保所有服务器实例都使用他们需要查找/更新会话的中央存储库。这将负责多服务器部署,而无需基于粘性会话的负载平衡。
将创建/更新/重新附加/删除会话的工作留给容器。它的建立是为了做到这一点。
现在,如果您认为这看起来像很多配置,并且对容器非常具体,我同意您的看法。但我也认为重复已经存在的功能(DRY)毫无意义。
如果我阅读了您的问题并尝试将其分解为功能,那么它基本上就是服务器如何处理Http会话,使用已识别的常规名称jsessionid
。因此,感觉这是定制现有功能的自然解决方案。
希望这会有所帮助。如果我误解了你的问题,请告诉我。