从自定义Servlet过滤器尝试访问GemFire会话对象时,它将采用容器的会话对象。会话对象的类型:
org.apache.catalina.session.StandardSessionFacade@517957e2
但是从Controller
开始,它工作正常。会话对象的类型为:
org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper$HttpSessionWrapper@5afe18ce
关于我们如何配置GemFire:
我们有旧版零售应用程序。最重要的是,我们使用了2.0.5
版本的GemFire。在 webappintializer 启动中,
AnnotationConfigWebApplicationContext rootContext =
new AnnotationConfigWebApplicationContext();
rootContext.register(GemfireConfig.class,RootConfig.class, SecurityConfig.class);
由于未将springSessionRepositoryFilter
Bean添加到过滤器链中,因此我们不得不使用以下命令向DelegatingFilterProxy
明确注册过滤器:
FilterRegistration.Dynamic springSessionRepositoryFilter =
container.addFilter("springSessionRepositoryFilter", DelegatingFilterProxy.class);
springSessionRepositoryFilter.addMappingForUrlPatterns(
EnumSet.allOf(DispatcherType.class), false, "/*");
在数据处理方面,为了获取会话对象,我们有一个getSession方法,该方法返回一个会话对象:
ServletRequestAttributes attr =
(ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpSession session = attr.getRequest().getSession();
当我们从getSession()
调用Controller
方法时,它按设计工作是绝对正常的。但是从Servlet过滤器调用相同的对象最终将获得Container创建的会话对象。
非常感谢您的帮助。
根据@John Blum的评论进行了重做,但仍然面临相同的问题。
答案 0 :(得分:0)
简而言之,为了Spring Session,特别是Spring Session for Pivotal GemFire(SSDG)的工作,SessionRepositoryFilter
(Javadoc,{{3} })向(Web)应用程序容器(例如Apache Tomcat,Eclipse Jetty等)注册时,必须是过滤器链中的第一个 Servlet过滤器。
否则,如果 Spring Session的 SessionRepositoryFilter
不是过滤器链中的第一个Servlet过滤器,则 Spring Session 将不会拦截HTTP请求(至今),将无法利用由HttpServletRequest来替换Container会话的机会(通过将SessionRepositoryFilter.SessionRepositoryRequestWrapper
换成Session
,请参见Source)来替换Container会话。使用由SessionRepository
实现确定的适当的提供程序(例如,带有SSDG的GemFire,例如> Spring Session )。{>在SessionRepositoryFilter
(here)上进行设置。>
您的Spring Web MVC应用程序Controller
起作用的原因是,Java EE Servlet规范/容器保证在用HTTP请求调用任何Servlet(即HttpServletRequest
)之前,所有Servlet过滤器都被调用。 。而且,由于Spring Web MVC DispatcherServlet
是正确的HttpServlet
,并且负责调用您的应用程序定义的Spring Web MVC Controllers
,因此可以保证应用程序Controllers
可以看到“已替换的” HTTP请求(扩展名为HTTP会话对象)。
那么,一些家政用品...我(不确定)您的意思是什么
2.0.5
版本的GemFire。 2.0.5
是指 Pivotal GemFire春季会议的最新版本 。
还有webappinitializer
吗?
对于#2,您是说专门创建了一个Spring here来手动手动注册SessionRepositoryFilter
(如上面的代码片段所示)吗?
您知道 Spring Session 已经提供了此类吗?WebApplicationInitializer
。
该类负责使用Spring的SessionRepositoryFilter
类(o.s.session.web.context.AbstractHttpServletApplicationInitializer
,然后是here和here来注册DelegatingFilterProxy
(注意{{1} }实例变量,默认为insertBeforeOtherFilters
),正确的顺序为here,具体来说,here)。
有趣的是,您似乎在上述“过滤器”注册代码的片段中正在做相同或相似的事情。
注意:此(Servlet容器的程序配置)仅在Servlet 3.0容器及更高版本中起作用。
您可以看到 Spring Session的 true
如何在here中使用,例如samples。有关AbstractHttpServletApplicationInitializer
的更多详细信息,请参见样本的相应here。
我注意到,关于Spring Initializer
类注册(以DelegatingFilterProxy
bean命名,名为“ springSessionRepositoryFilter”)的另一件事是,您将SessionRepositoryFilter
作为第二个DelegatingFilterProxy.class
的参数,如下所示...
servletContext.addFilter("filterName", <FilterType>);
但是, Spring Session (核心)本身实际上guide docs(具有“ springSessionRepositoryFilter” bean名称)是Spring FilterRegistration.Dynamic springSessionRepositoryFilter =
container.addFilter("springSessionRepositoryFilter", DelegatingFilterProxy.class);
类和constructs and initializes的实例注册时使用DelegatingFilterProxy
方法(第二个参数)的“实例”。
我怀疑ServletContext.addFilter(..)
API本身在构造/初始化实例时仅使用Spring ServletContext.addFilter(..)
类的默认构造函数,这可能是问题的根源,尤其是在以编程方式注册Servlet Filter时
令人回味的食物。
希望这会有所帮助!