第一次请求时,会话为空

时间:2015-04-09 13:24:31

标签: spring-session

我使用春季会议,我真的很喜欢它。但是我觉得我错过了什么。在我的应用程序中,流程如下: 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,这是一个演示问题的示例应用程序:

https://github.com/paranoiabla/spring-session-issue

2 个答案:

答案 0 :(得分:2)

如果您想要获取会话,则不应使用请求的会话ID。请求的会话ID就是......浏览器请求的内容。使用请求会话的一些问题(其中一些已经概述过):

  • 如果您清除所有Cookie并发出请求,则浏览器不会请求任何会话。
  • 正如您所指出的,如果数据存储重新启动并且不是持久性的,那么请求的会话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透明处理。