在 Servlet 过滤器中调用容器的会话对象而不是 GemFire 的会话对象

当尝试访问 GemFire 会话对象时,自定义 Servlet 过滤器会使用容器的会话对象。会话对象的类型为:


org.apache.catalina.session.StandardSessionFacade@517957e2


但是从Controller,它工作正常。会话对象的类型为: org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper$HttpSessionWrapper@5afe18ce


关于我们如何配置 GemFire:


我们有一个传统的零售应用程序。最重要的是,我们使用了2.0.5GemFire 版本。在webappintializer启动时,


AnnotationConfigWebApplicationContext rootContext = 

    new AnnotationConfigWebApplicationContext();


rootContext.register(GemfireConfig.class,RootConfig.class, SecurityConfig.class);

由于springSessionRepositoryFilterbean没有添加到过滤器链中,我们必须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 过滤器调用相同的方法最终会获得容器创建的会话对象。


任何帮助深表感谢。


根据@John Blum 的评论重新设计,但仍然面临同样的问题。


POPMUISE
浏览 159回答 2
2回答

冉冉说

简而言之,为了让Spring Session,特别是用于 Pivotal GemFire&nbsp;(SSDG) 的Spring Session来完成它的工作,SessionRepositoryFilter(&nbsp;Javadoc&nbsp;,&nbsp;Source&nbsp;)在向您的 (Web) 注册时必须是过滤器链中的第一个Servlet 过滤器应用程序容器(例如 Apache Tomcat、Eclipse Jetty 等)。否则,如果Spring Session&nbsp;SessionRepositoryFilter不是过滤器链中的第一个 Servlet 过滤器,那么Spring Session将不会(还)拦截 HTTP 请求,并且将无法行使替换 Container 会话的机会(通过HttpServletRequest用SessionRepositoryFilter.SessionRepositoryRequestWrapper,请参阅此处) 使用Session由Spring Session提供的使用适当的提供程序(例如 GemFire 和 SSDG),由SessionRepository在SessionRepositoryFilter(此处)上设置的实现确定。您的 Spring Web MVC 应用程序Controller工作的原因是,Java EE Servlet Spec/Container 保证在使用 HTTP 请求(即HttpServletRequest)调用任何 Servlet 之前调用所有 Servlet 过滤器。并且,由于 Spring Web MVCDispatcherServlet是一个适当的HttpServlet并且负责调用您的应用程序定义的 Spring Web MVC&nbsp;Controllers,因此应用程序Controllers可以保证看到“替换”的 HTTP 请求(以及扩展的 HTTP 会话对象)。所以,一些内务管理项目......我不确定(完全)你的意思是:2.0.5GemFire 的版本。&nbsp;2.0.5指的是Pivotal GemFire的Spring Session的最新/当前版本。和webappinitializer?对于#2,您的意思是您专门创建了一个 SpringWebApplicationInitializer来显式注册SessionRepositoryFilter, 手动(如上面的代码片段所示)?你知道春季会议已经提供了这样一类...&nbsp;o.s.session.web.context.AbstractHttpServletApplicationInitializer。这个类负责注册SessionRepositoryFilterusing Spring 的DelegatingFilterProxy类(这里,然后这里和这里(注意insertBeforeOtherFilters实例变量,默认为true),并以正确的顺序,这里,嗯,具体来说,这里)。有趣的是,在上面的过滤器注册代码片段中,您似乎正在做相同或相似的事情。注意:这(Servlet 容器的编程配置)仅适用于 Servlet 3.0 容器及更高版本。您可以在示例中看到Spring Session 是&nbsp;如何AbstractHttpServletApplicationInitializer使用的,例如,这里。有关更多详细信息,请参见示例的相应指南文档。Initializer我注意到的关于您的 SpringDelegatingFilterProxy类注册(以SessionRepositoryFilterbean 命名,名为“springSessionRepositoryFilter”)的不同之处是,您将 传递给DelegatingFilterProxy.class的第二个参数servletContext.addFilter("filterName", <FilterType>);,如下所示...FilterRegistration.Dynamic&nbsp;springSessionRepositoryFilter&nbsp;=&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;container.addFilter("springSessionRepositoryFilter",&nbsp;DelegatingFilterProxy.class);然而,春季会议(核心)本身实际上构造并初始化(与“springSessionRepositoryFilter”豆名)春天的一个实例DelegatingFilterProxy类,并通过该“实例”的ServletContext.addFilter(..)有关登记方法(第二个参数)。我怀疑ServletContext.addFilter(..)API 本身DelegatingProxyFilter在构造/初始化实例时仅使用 Spring类的默认构造函数,这可能是您问题的根源,尤其是在以编程方式注册 Servlet 过滤器时。深思熟虑。希望这可以帮助!

一只名叫tom的猫

在尝试了这些建议后,问题仍然存在。现在,我们不再对SessionRepositoryFilter. 我们现在使用:class WebAppInitializer extends AbstractHttpSessionApplicationInitializer {&nbsp;public WebAppInitializer() {&nbsp; &nbsp; &nbsp; &nbsp; super(GemfireConfig.class,X.class, Y.class); //X&Y are preexisting config classes in the application context&nbsp; &nbsp; }@Overridepublic void onStartup(ServletContext container) throws ServletException {&nbsp; &nbsp; super.onStartup(container); // newly added inorder to call AbstractHttpSessionApplicationInitializer.startup()&nbsp; &nbsp; ...//existing code&nbsp; &nbsp; ...//}删除了 springSessionRepositoryFilter 的显式注册。当我们查看堆栈跟踪时,我们可以看到这个过滤器首先被调用。因此,过滤器链的顺序似乎是完整的。我们遇到问题的过滤器正在被调用。即使没有提到的更改,这也是相同的行为。尽管如此,过滤器中的会话对象仍来自容器。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java