2

I'm using spring-session and I really like it. However I think I'm missing something. In my application the flow goes like this: 1) User requests HomepageController and that controller tries to put an attribute in the request:

    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);
        }
    }

As you can see it will try to get the sessionID from the request-cookie, and if there's a session with that ID in the repository than use it (add attribute). This is perfect, but only after the second request. Why? Because if I restart the server than the cookie is left with the old value, and then the first request will not find the session in the repository. After the response is committed though the cookie will be updated, so the second request will be correct. And here's the question: what is wrong with my logic and how should one develop the application in order to support the first request too?

BTW, here's a sample application that demonstrates the problem:

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

4

2 回答 2

2

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

  • 如果您清除所有 cookie 并发出请求,则浏览器不会请求会话。
  • 正如您所指出的,如果数据存储重新启动并且不是持久的,那么请求的会话 ID 无效
  • 如果会话过期,则请求的会话将无效

相反,您应该使用会话 ID:

final String sessionIds = request.getSession().getId();

如果请求的会话 id 有效,这将使用它,否则它将创建一个新会话并确保将会话写入响应(即作为 cookie 包含在响应中)。

于 2015-04-15T01:42:22.970 回答
0

我会说你的方法是错误的,你的控制器做了很多事情,你应该只使用HttpSessionSpring Session 提供支持的。您也不应该将会话放在model恕我直言中,因为您应该只是访问HttpSession. 您的应用程序不应该知道 Spring Session。

您的控制器应如下所示

@Controller
public class HomepageController {

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(HttpSession session) {
        session.setAttribute("attr", "value");
        return "homepage";
    }
}

如果您不想强制创建会话,请注入HttpServletRequestand dogetSession(false)而不是注入HttpSession.

其他一切(在请求处理后存储会话等)将由 Spring Session 透明地处理。

于 2015-05-02T11:11:52.353 回答