【问题标题】:Can session scope beans be used with Spring Session and GemFire?会话范围 bean 可以与 Spring Session 和 GemFire 一起使用吗?
【发布时间】:2017-08-14 12:03:38
【问题描述】:

“会话”范围 bean 能否与 Spring Session 和 Pivotal GemFire 一起使用?

当将 Spring Session 用于“会话”范围 bean 时,Spring 会为此 bean 创建一个额外的 HttpSession。这是一个现有的问题吗?

解决办法是什么?

【问题讨论】:

  • 上述查询有什么解决办法吗?
  • 对下面的解决方案和答案有任何疑问吗?
  • 1 last comment... 我在 Spring Session Data GemFire 的最新版本中构建了一个示例,2.0.0.RC1(只是昨天发布...spring.io/blog/2017/11/07/…) 演示了 Spring "session" 范围代理如何在配置有 Spring SessionSpring Boot 应用程序的上下文中工作i>(使用 GemFire/Geode 作为提供者)。看这里...docs.spring.io/autorepo/docs/spring-session-data-geode-build/…

标签: spring-session spring-data-gemfire


【解决方案1】:

关于...

会话范围的 bean 可以与 Spring Session 和 GemFire 一起使用吗?

是的!

事实上,与 Spring Session 一起使用哪个底层“提供程序”也没有关系。例如,Spring Session with GemFire/Geode (docs) 或 Spring Session with Redis (docs) 等都可以使用,并且工作方式相同(以相同的方式)。

至于……

如果对会话范围的 bean 使用 Spring Session,Spring 会为此 bean 创建额外的 HttpSession,这是一个现有问题吗?

嗯,这完全正确。

您必须了解这里使用的底层技术以及它们如何协同工作,包括 Spring SessionSpring 框架Servlet 框架 em>,您的 Web 容器(例如 Tomcat),受 Java EE Servlet 规范中指定的合同的约束,以及您可能应用的任何其他技术(例如 Spring Security 的 Web 支持)。

如果我们深入了解 Spring 的 架构/基础架构,您将开始了解它的工作原理、工作原理以及您的特定陈述(“Spring 创建了一个extra 此 bean 的 HttpSession")正确。

首先,Spring Session 注册了一个非常重要的 Servlet Filtero.s.session.web.http.SessionRepositoryFilter

有许多不同的方法可以做到这一点,javax.servlet.FilterJavadoc 基本上暗示这是通过 Web 应用程序“部署描述符”完成的。 p>

当然,考虑到我们今天的配置选项,Web 应用程序部署描述符 的定义相当松散,但我们通常知道这意味着web.xml。但是,这并不是我们可以配置 Web 应用程序的 ServletContext 的唯一方法。

Spring 支持基于 web.xml部署描述符 以及使用 ServletJavaConfig (3.0+ ) API。

web.xml 中,您将register(对于exampleSpring Frameworks' o.s.web.filter.DelegatingFilterProxy,它代表一个实际的javax.servlet.Filter 实现(当Spring Session 正在发挥作用,那当然是o.s.session.web.http.SessionRepositoryFilter),它也被声明/定义为“bean”(首先是this,然后是this)在弹簧容器。这是必要的,以便自动连接(注入)适当的 Spring Session o.s.session.SessionRepository 实现(也是容器中定义的 Spring 托管 bean,例如 Redis ) 知道如何将 (HTTP) Session 状态管理委托给底层的“提供者”。

JavaConfig 方法中,注册是通过核心 Spring Framework 的 o.s.web.WebApplicationInitializer 概念执行的。阅读 Javadoc 了解更多详情。

嗯,Spring Session 提供了这样一个WebApplicationInitializer 来初始化(HTTP)会话管理,o.s.session.web.context.AbstractHttpSessionApplicationInitializer。通常,当使用 Spring 的 Java-based Container Configuration 和/或 Annotation configuration 方法时,开发人员将创建一个扩展此 Spring Session 提供的类和 register 必要配置的类(例如连接标准)底层会话管理提供者;对于example(另见this)。 Config 类是 annotated@EnableRedisHttpSession 其中 imports Spring @Configuration 类声明/定义适当的 Spring Session SessionRepository 实现Servlet Filter(又是 SessionRepositoryFilter)需要的“提供者”(例如 Redis)。

如果你看看 Spring Session AbstractHttpSessionApplicationInitializer 做了什么,你会发现它registers Spring SessionSessionRepositoryFilter,间接通过 Spring Framework 的 DelegatingFilterProxy... 从插入开始,然后是 here,然后是 here,最后是 here

如您所见,Spring Session SessionRepositoryFilterServlet Filters 链中的 positioned first!insertBeforeOtherFilters 被否定,因为javax.servlet.FilterRegistration.Dynamic.addMappingForUrlPatterns(dispatcherTypes, isMatchAfter, urlPatterns...) 中的参数是“isMatchAfter”。

这是必不可少的,因为 春季会议的 o.s.session.web.http.SessionRepositoryFilter replaces javax.servlet.http.HttpServletRequestjavax.servlet.http.HttpServletResponse。具体来说,通过替换 javax.servlet.http.HttpServletRequestSpring Session 可以提供由 Spring Session 和提供者支持的 javax.servlet.http.HttpSession(当调用 HttpServletRequest.getSession(..) 时)的实现开发人员的选择(例如 Redis、GemFire),首先是 Spring Session 的全部目的。

因此,Servlet Filters 在任何框架代码(例如 Spring Framework 的 会话范围 bean 基础结构)之前查看 HTTP 请求/响应,尤其是在任何Web 应用程序的ControllersServlets,可以查看HTTP 请求/响应。

所以,当核心 Spring 框架的 会话范围的 bean 基础设施看到(HTTP)Servlet 请求/响应时,它会看到 Spring Session交给它,这只是 Spring Session 支持的常规javax.servlet 接口(例如HttpSession)的实现。

查看核心 Spring 框架的o.s.web.context.request.SessionScope“自定义”实现(处理在 Spring 容器中声明/定义的会话范围 bean 的 bean 引用/bean 生命周期) ,它扩展了o.s.web.context.request.AbstractRequestAttributesScope,您会看到它只是委托给o.s.web.context.request.SessionRequestAttributes 类。此类主要由 Spring 的 DispatcherServlet 创建,并根据相关 bean(定义)定义的“提供”范围定义其所有操作(例如 setAttribute(name, value, scope))。有关详细信息,请参阅source。因此 bean 被添加到适当的 HTTP 会话中。

当然,Spring "will" create a new javax.servlet.http.HttpSession 在第一个 HTTP 请求上,但不是没有 Spring Session 的 基础设施知道它,因为 Spring在这种情况下,em> 使用的是由 Spring Session 的Session”支持的javax.servlet.http.HttpSession 的实现。

此外,getSession(true) 也只是表示如果 HttpSession 尚不存在,则“允许”创建它! Servlet 容器不会继续为每个 HTTP 请求创建新的 HTTP 会话,只要会话 ID 可以从 HTTP 请求中确定(通过 URL 注入完成...jsessionid或使用 cookie,通常)。有关详细信息,请参阅javax.servlet.HttpServletRequest.getSession(boolean)

无论如何,对整个故事的唯一其他警告是,您需要确保,尤其是对于 GemFire,...

  1. 容器中定义的 Spring“会话”范围 bean 是可序列化的,可以使用 Java 序列化,也可以使用 GemFire's serialization strategies 中的 1 个。这包括任何 bean 引用(其他 bean、对象类型等),除非这些“引用”声明为 transient。注意:我不完全确定基于 GemFire 反射的 PDX 序列化方法完全“了解”“transient”字段。请注意这一点。

  2. 您必须确保会话中序列化的类位于 GemFire 服务器类路径中。

我是 working on a configuration option Spring Session Data Geode/GemFire 目前支持 PDX,但目前可用。

无论如何,我希望这有助于稍微清理一下浑水。我知道要消化的内容很多,但一切都应该按照用户的期望进行。

我还要补充一点,我也没有测试过这个。但是,在查看代码后,我很确定这应该可以工作。

我有made it a task 在不久的将来添加测试和样本以涵盖这种情况。

干杯! -约翰

【讨论】:

    猜你喜欢
    • 2011-01-09
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 2012-10-31
    • 1970-01-01
    • 2011-02-06
    • 1970-01-01
    • 2011-07-05
    相关资源
    最近更新 更多