可以"会话"范围bean与 Spring Session 和Pivotal GemFire一起使用?
使用 Spring Session 进行" session"范围bean, Spring 为此bean创建额外的HttpSession
。这是一个现存的问题吗?
这是什么解决方案?
答案 0 :(得分:4)
...关于
会话范围bean可以与Spring Session和GemFire一起使用吗?
是!
事实上,哪个底层&#34;提供商&#34;并不重要。与 Spring Session 一起使用。例如,可以使用Spring Session with GemFire/Geode(docs)或Spring Session with Redis(docs)等,它们的工作方式相同(以相同的方式)。< / p>
至于......
如果对会话作用域使用Spring Session,Spring会为这个bean创建额外的HttpSession,这是一个现存的问题吗?
嗯, 完全正确。
您必须了解这里的基础技术以及它们如何协同工作,包括 Spring Session , Spring Framework , Servlet Framework ,您的 Web容器(例如Tomcat),它受Java EE Servlet 规范中指定的合同以及您可能已应用的任何其他技术的约束(例如< em> Spring Security的 Web支持)。
如果我们深入了解 Spring的架构/基础架构,您将开始了解它的工作原理,工作原理以及您的特定声明(&#34; Spring为此bean创建额外 HttpSession &#34;)不正确。
首先, Spring Session 注册一个重要的 Servlet Filter
,o.s.session.web.http.SessionRepositoryFilter
。
有许多不同的方法可以做到这一点,javax.servlet.Filter
的 Javadoc 实质上暗示这是通过Web应用程序&#34; 部署描述符&#34;
当然,考虑到我们今天的配置选项,Web应用程序部署描述符的定义非常松散,但我们通常都知道这意味着web.xml
。但是,这不是我们可以配置Web应用程序ServletContext
的唯一方式。
Spring 使用 Servlet 支持基于web.xml
的部署描述符以及 JavaConfig ( 3.0+)API。
在web.xml
中,您register(对于example) Spring Frameworks&#39; o.s.web.filter.DelegatingFilterProxy
,代表实际javax.servlet.Filter
1}}实现(当 Spring Session 正在运行时,当然是o.s.session.web.http.SessionRepositoryFilter
),它也被声明/定义为&#34; bean &#34; Spring 容器中的第一个this,然后是this)。这是必要的,以便自动连接(注入)适当的 Spring Session o.s.session.SessionRepository
实现(也是容器中定义的 Spring 托管bean,例如{ {3}})知道如何将(HTTP)Session
状态管理委托给底层&#34;提供商&#34;。
在 JavaConfig 方法中,注册是通过核心 Spring Framework的 Redis概念执行的。阅读Javadoc了解更多详情。
嗯, Spring Session 提供了WebApplicationInitializer
初始化(HTTP)会话管理o.s.web.WebApplicationInitializer
。通常,在使用 Spring o.s.session.web.context.AbstractHttpSessionApplicationInitializer
和/或Java-based Container Configuration方法时,开发人员会创建一个扩展此 Spring Session 的类class和Annotation configuration基础会话管理提供者的必要配置(例如连接标准);对于register(另见example)。 Config
类为this,@EnableRedisHttpSession
annotated Spring @Configuration
类声明/定义相应的 Spring &#34;提供商&#34;的会话 SessionRepository
实施(例如,再次imports),这是 Servlet Filter
所需的(再次SessionRepositoryFilter
)。
如果你看一下 Spring Session AbstractHttpSessionApplicationInitializer
的作用,你会看到{{3>} Spring Session ,{{1} },间接通过 Spring Framework&#39> <{em> SessionRepositoryFilter
...来自插入,然后是Redis,然后是registers,最后是here。
如您所见, Servlet DelegatingFilterProxy
链中的 Spring Session SessionRepositoryFilter
为here。由于here中的参数为&#34; isMatchAfter &#34;。
Filters
被否定。
这是必不可少的,因为 Spring Session&#39> !insertBeforeOtherFilters
positioned first o.s.session.web.http.SessionRepositoryFilter
和javax.servlet.http.HttpServletRequest
。具体来说,通过替换javax.servlet.http.HttpServletResponse
, Spring Session 可以提供由{em> Spring Session <支持的javax.servlet.http.HttpServletRequest
(当调用javax.servlet.http.HttpSession
时)的实现/ em>和开发人员的选择提供商(例如Redis,GemFire),首先是 Spring Session 的全部目的。
因此, Servlet HttpServletRequest.getSession(..)
在任何框架代码(例如 Spring Framework&#39> s 会话范围的bean基础结构)之前看到HTTP请求/响应,特别是在任何Web应用程序Filters
或Controllers
之前,请查看HTTP请求/响应。
因此,当核心 Spring Framework的会话作用域bean基础结构看到(HTTP) Servlet 请求/响应时,它会看到 Spring会话交给它,这只是一个由 Spring Session 支持的常规Servlets
接口(例如javax.servlet
)的实现。
查看核心 Spring Framework&#39> javax.servlet.FilterRegistration.Dynamic.addMappingForUrlPatterns(dispatcherTypes, isMatchAfter, urlPatterns...)
&#34; custom&#34;实现(处理 Spring 容器中声明/定义的会话范围bean的bean引用/ bean生命周期),扩展HttpSession
,你看到它只是委托给replaces类。该类主要由 Spring&#39> <{em> o.s.web.context.request.AbstractRequestAttributesScope
创建,并根据&#34;提供的&#34;定义其所有操作(例如o.s.web.context.request.SessionScope
)。由所讨论的bean(定义)定义的范围。有关详细信息,请参阅o.s.web.context.request.SessionRequestAttributes
。因此bean被添加到适当的HTTP会话中。
当然, Spring setAttribute(name, value, scope)
DispatcherServlet
在第一个HTTP请求上,但不是没有 Spring Session的基础设施知道它,因为 Spring 在这种情况下使用的是由{em> Spring Session&#39> &#34; javax.servlet.http.HttpSession
&#支持的javax.servlet.http.HttpSession
的实现34。
另外,source也表示Session
是&#34; 允许&#34;如果它还不存在就被创建! Servlet 容器根本不会为每个HTTP请求创建新的HTTP会话,只要可以从HTTP请求确定会话ID(通过URL注入完成... {{1或者通常使用cookie)。有关详细信息,请参阅"will" create a new。
无论如何,对整个故事唯一的另一个警告是,你需要确保,特别是对于GemFire,......
Spring &#34; session&#34;容器中定义的scoped bean可以使用Java Serialization或getSession(true)
中的1个进行序列化。这包括bean引用(其他bean,对象类型等),除非那些&#34;引用&#34;声明为HttpSession
。注意:我并不完全确定基于GemFire Reflection的PDX序列化方法是完全&#34;意识到&#34; &#34; transient &#34;领域。要注意这一点。
您必须确保会话中序列化的类位于GemFire Servers类路径中。
目前我是javax.servlet.HttpServletRequest.getSession(boolean)
用于支持PDX的Spring Session Data Geode / GemFire,但 尚未提供。
无论如何,我希望这有助于清理泥泞的水域。我知道要消化很多,但这一切都应该像用户期望的那样工作。
我还要补充一点,我还没有测试过这个。但是,在查看代码之后,我很确定这应该可行。
我有GemFire's serialization strategies在不久的将来添加测试和样本以涵盖这种情况。
干杯! -John