Java 集装箱';s会话对象,而不是GemFire';在Servlet筛选器中调用的会话对象

Java 集装箱';s会话对象,而不是GemFire';在Servlet筛选器中调用的会话对象,java,spring,spring-session,gemfire,spring-data-gemfire,Java,Spring,Spring Session,Gemfire,Spring Data Gemfire,当试图访问GemFire会话对象时,它从自定义Servlet过滤器中获取容器的会话对象。会话对象的类型为: org.apache.catalina.session。StandardSessionFacade@517957e2 但是从控制器,它工作正常。会话对象的类型为: org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper$HttpSessionWrapper@5a

当试图访问GemFire会话对象时,它从自定义Servlet过滤器中获取容器的会话对象。会话对象的类型为:

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

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

关于我们如何配置GemFire:

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

由于
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();
当我们从
Controller
调用
getSession()
方法时,它的工作完全符合设计要求。但是从Servlet过滤器调用相同的函数最终会得到容器创建的会话对象

非常感谢您的帮助


根据@John Blum的评论进行了修改,但仍然面临相同的问题。

简而言之,为了(特别是,(SSDG)完成其工作,
SessionRepositoryFilter
(,)必须是在(Web)应用程序容器中注册时过滤器链中的第一个Servlet过滤器(例如ApacheTomcat、Eclipse Jetty等)

否则,如果Spring会话的
SessionRepositoryFilter
不是过滤器链中的第一个Servlet过滤器,那么Spring会话将不会截获HTTP请求,也无法利用它的机会来替换容器会话(通过使用
SessionRepositoryFilter.SessionRepositoryRequestWrapper
包装
HttpServletRequest
,请参阅)使用Spring Session使用适当的提供程序提供的
会话(例如,使用SSDG的GemFire),由
SessionRepository
实现确定,该实现在
SessionRepositoryFilter
()上设置

SpringWebMVC应用程序
Controller
工作的原因是,JavaEEservlet规范/容器保证在使用HTTP请求调用任何Servlet之前调用所有Servlet过滤器(即
HttpServletRequest
)。而且,由于Spring Web MVC
DispatcherServlet
是一个合适的
HttpServlet
,并负责调用应用程序定义的Spring Web MVC
控制器
,因此应用程序
控制器
保证可以看到“替换”的HTTP请求(扩展为HTTP会话对象)

所以,有一些家政用品……我(确切地)不确定你说的是什么意思:

  • 2.0.5
    版本的GemFire。
    2.0.5
    是指关键GemFire的最新/最新版本的春季课程

  • webappinitializer

  • 对于#2,您的意思是专门创建了一个Spring来显式地手动注册
    SessionRepositoryFilter
    (如上代码片段所示)

    您知道吗,Spring会话已经提供了这样一个类

    这个类负责使用Spring的
    DelegatingFilterProxy
    类注册
    SessionRepositoryFilter
    (,then,and)(注意
    insertBeforeOtherFilters
    实例变量,它默认为
    true
    ),并且顺序正确

    有趣的是,看起来您在上面的过滤器注册代码片段中做了相同或类似的事情

    注意:此(Servlet容器的编程配置)仅适用于Servlet3.0容器和更高版本

    例如,您可以看到Spring会话的
    AbstractHttpServletApplicationInitializer
    是如何在中使用的

    我注意到Spring
    DelegatingFilterProxy
    类注册(以
    SessionRepositoryFilter
    bean命名,名为“springSessionRepositoryFilter”)的一个不同之处是,您将
    DelegatingFilterProxy.class
    作为
    servletContext.addFilter(“filterName”)的第二个参数传递给;
    ,如图所示

    FilterRegistration.Dynamic springSessionRepositoryFilter = 
        container.addFilter("springSessionRepositoryFilter", DelegatingFilterProxy.class);
    
    但是,Spring会话(core)本身(使用“springSessionRepositoryFilter”bean名称)实际上是Spring
    DelegatingFilterProxy
    类的一个实例,并且在注册时将该“实例”添加到
    ServletContext.addFilter(…)
    方法(第二个参数)

    我怀疑
    ServletContext.addFilter(..)
    API本身在构造/初始化实例时只使用了Spring
    DelegatingProxyFilter
    类的默认构造函数,这可能是问题的根源,尤其是在以编程方式注册Servlet过滤器时

    值得深思


    希望这有帮助!

    在尝试了这些建议后,问题仍然存在。现在,我们不再为
    SessionRepositoryFilter
    单独注册。我们现在使用:

    class WebAppInitializer extends AbstractHttpSessionApplicationInitializer {
    
     public WebAppInitializer() {
            super(GemfireConfig.class,X.class, Y.class); //X&Y are preexisting config classes in the application context
    
        }
    
    @Override
    public void onStartup(ServletContext container) throws ServletException {
    
        super.onStartup(container); // newly added inorder to call AbstractHttpSessionApplicationInitializer.startup()
        ...//existing code
        ...//
    
    }
    
    删除了springSessionRepositoryFilter的显式注册

    当我们查看堆栈跟踪时,我们可以看到这个过滤器首先被调用。因此,过滤器链的顺序看起来是完整的

    我们面临的问题是,过滤器在之后被调用。即使没有提到的更改,这也是相同的行为

    不过,筛选器中的会话对象来自容器。

    您不需要
    class WebAppInitializer extends AbstractHttpSessionApplicationInitializer {
    
     public WebAppInitializer() {
            super(GemfireConfig.class,X.class, Y.class); //X&Y are preexisting config classes in the application context
    
        }
    
    @Override
    public void onStartup(ServletContext container) throws ServletException {
    
        super.onStartup(container); // newly added inorder to call AbstractHttpSessionApplicationInitializer.startup()
        ...//existing code
        ...//
    
    }