使用spring-session获取当前会话

时间:2015-03-24 14:20:05

标签: spring-session

这是我的问题:我正在编写一个平台,我将给予客户实​​施他们的项目。所以在我的平台上,我创建了一个SessionService,其中我有getCurrentSessiongetAttributesetAttribute等方法。在春季会议之前我的getCurrentMethod看了像这样:

@Override public HttpSession getCurrentSession() { if (this.session == null) { final ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); return attr.getRequest().getSession(true); // true == allow create } return this.session; }

虽然它看起来很丑陋并且没有像redis这样的支持,但效果非常好。现在我想迁移到spring-session,我希望使用SessionRepository来查找用户的当前会话,但我只能看到getSession(String id)。我相信id存储在cookie中,因此要使用它,我可能必须将HttpServletRequest对象从我的控制器传递到我的外观,再到非常接近db层的服务层。这看起来对我来说是一个非常糟糕的主意,所以我的问题是:有没有办法让currentSession接近数据库层?我想的一种方法是编写一个将被调用控制器的拦截器,它将在存储库中设置当前会话,或者服务可能?我只是不确定这是正确的方法。

1 个答案:

答案 0 :(得分:1)

从服务层获取会话ID

您可以使用RequestContextHolder检索会话ID,设置属性和删除属性。

RequestContextHolder通常使用RequestContextListenerRequestContextFilter进行设置。 Spring Session不能与RequestContextListener一起使用,因为在调用RequestContextListener之前,Spring Session无法包装请求。

不幸的是,这意味着对于Spring Boot应用程序,RequestContextHolder无法开箱即用。要解决它,您可以创建一个RequestContextFilter Bean。有关此问题的更新,请参阅spring-boot/gh-2637

我应该把它放进会话吗?

仅仅因为在会话中放置大量对象并将其存储在Redis中并不意味着它是正确的做法。

请记住,每次请求都会检索整个会话。因此,当Redis速度很快时,如果会话中有很多对象,这会产生重大影响。显然,实现可以针对您的情况进行优化,但我认为会话的概念通常具有此属性。

一般的经验法则是,"我的95%以上的请求是否需要此对象?" (读这几乎是我的所有要求)。如果是这样,它可能是会话的候选人。在大多数情况下,如果符合此标准,则该对象应与安全相关。

我应该从服务层的ThreadLocal访问会话ID吗?

这肯定是开放的辩论,因为代码既是一门艺术,也是一门科学。

但是,我认为您不应该从整个架构中的线程区域设置变量中获取会话ID。这样做有点像获得一个" Person id"并获得当前"人员ID"来自ThreadLocale中的HttpServletRequest。相反,应从控制器获取值并将其传递到服务层。