0

这是我的问题:我正在编写一个平台,我将提供给客户来实施他们的项目。所以在我的平台上,我创建了一个SessionService方法,其中我有类似getCurrentSession, getAttribute,setAttribute等的方法。在 spring-session 之前我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 靠近 db 层?我认为的一种方法是编写一个拦截器,该拦截器将被调用控制器,它将在存储库中设置当前会话,或者可能是服务?我只是不确定这是正确的方法。

4

1 回答 1

1

从服务层获取会话 ID

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

通常RequestContextHolder使用RequestContextListener或设置RequestContextFilter。Spring Session 不起作用,RequestContextListener因为 Spring Session 无法在RequestContextListener调用之前包装请求。

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

我应该把这个放在会议上吗?

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

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

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

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

这当然是有争议的,因为代码既是一门艺术,也是一门科学。

但是,我认为您不应该在整个体系结构中从线程语言环境变量中获取会话 ID。这样做感觉有点像从 ThreadLocale 中的 HttpServletRequest 获取“Person id”并获取当前“Person id”。相反,应该从控制器获取值并将其传递到您的服务层。

于 2015-03-31T13:01:57.350 回答