我使用春季会议,我真的很喜欢它。但是我觉得我错过了什么。在我的应用程序中,流程如下:
1)用户请求HomepageController
,该控制器尝试在请求中放置一个属性:
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
final String sessionIds = sessionStrategy.getRequestedSessionId(request);
if (sessionIds != null) {
final ExpiringSession session = sessionRepository.getSession(sessionIds);
if (session != null) {
session.setAttribute("attr", "value");
sessionRepository.save(session);
model.addAttribute("session", session);
}
}
正如您所看到的,它将尝试从请求cookie中获取sessionID,并且如果在存储库中具有该ID的会话比使用它(添加属性)。这是完美的,但仅在第二次请求之后。为什么?因为如果我重新启动服务器而不是使用旧值保留cookie,那么第一个请求将无法在存储库中找到该会话。提交响应后,虽然cookie会更新,但第二次请求将是正确的。 这就是问题:我的逻辑出了什么问题?如何开发应用程序以支持第一个请求?
BTW,这是一个演示问题的示例应用程序:
答案 0 :(得分:2)
如果您想要获取会话,则不应使用请求的会话ID。请求的会话ID就是......浏览器请求的内容。使用请求会话的一些问题(其中一些已经概述过):
相反,您应该使用会话ID:
final String sessionIds = request.getSession().getId();
如果它有效,这将使用所请求的会话ID,否则它将创建一个新会话并确保会话被写入响应(即作为cookie包含在响应中)。
答案 1 :(得分:0)
我想说你的方法是错误的,你的控制器做得很多,你应该只使用Spring Session提供支持的HttpSession
。您也不应该将会话放在model
imho中,因为您应该只访问HttpSession
。您的应用程序不应该了解Spring Session。
您的控制器应如下所示
@Controller
public class HomepageController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(HttpSession session) {
session.setAttribute("attr", "value");
return "homepage";
}
}
如果您不想强制创建会话,请注入HttpServletRequest
并执行getSession(false)
而不是注入HttpSession
。
其他所有内容(在请求处理之后存储会话等)将由Spring Session透明处理。