簡體   English   中英

在Servlet過濾器內部調用容器的會話對象而不是GemFire的會話對象

[英]Container's session object and not GemFire's session object is invoked inside Servlet Filter

嘗試訪問GemFire會話對象時,來自自定義Servlet過濾器的方法是改用Container的會話對象。 會話對象的類型為:

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添加到過濾器鏈,我們必須與明確登記過濾器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過濾器調用相同的對象最終會得到Container創建的會話對象。

任何幫助深表感謝。

根據@John Blum的評論進行了重做,但仍然面臨相同的問題。

簡而言之,為了使Spring Session (特別是Pivotal GemFire (SSDG)的Spring Session )能夠完成其工作, SessionRepositoryFilterJavadocSource )必須是在向(Web站點)注冊時在過濾器鏈中的第一個 Servlet過濾器。 )應用程序容器(例如Apache Tomcat,Eclipse Jetty等)。

否則,如果Spring Session的 SessionRepositoryFilter不是過濾器鏈中的第一個Servlet Filter,則Spring Session不會(尚未)攔截HTTP請求,並且將無法利用其機會來替換Container會話(通過包裝HttpServletRequestSessionRepositoryFilter.SessionRepositoryRequestWrapper ,見這里 )有一個Session使用合適的供應商(由春季會議提供如喜歡的GemFire與SSDG),由確定的SessionRepository實現,這是在設置SessionRepositoryFilter在這里 )。

您的Spring Web MVC應用程序Controller工作的原因是,Java EE Servlet規范/容器保證在用HTTP請求(即HttpServletRequest )調用任何Servlet之前,將調用所有Servlet過濾器。 而且,由於Spring Web MVC DispatcherServlet是適當的HttpServlet並負責調用應用程序定義的Spring Web MVC Controllers ,因此可以確保應用程序Controllers可以看到“已替換”的HTTP請求(並且通過擴展名,HTTP會話對象)。

因此,一些家政服務項目...我(確切)不確定您的意思是:

  1. GemFire的2.0.5版本。 2.0.5是指適用於Pivotal GemFireSpring Session的最新/當前版本。

  2. webappinitializer嗎?

對於#2,您是否意味着專門創建了一個Spring WebApplicationInitializer來手動顯式注冊SessionRepositoryFilter (如上面的代碼片段所示)?

您是否知道Spring Session已經提供了這樣的類... ossession.web.context.AbstractHttpServletApplicationInitializer

此類負責使用Spring的DelegatingFilterProxy類( herehereherehere) (注意insertBeforeOtherFilters實例變量,默認為true ),並以正確的順序在此處 (尤其是在此處 )注冊SessionRepositoryFilter

有趣的是,您似乎在上述“過濾器”注冊代碼的片段中正在做相同或相似的事情。

注意:此(Servlet容器的程序配置)僅在Servlet 3.0容器及更高版本中有效。

例如,您可以在此處查看如何在示例中使用Spring Session的 AbstractHttpServletApplicationInitializer 有關Initializer更多詳細信息,請參見示例的相應指南文檔

我注意到,與您的Spring DelegatingFilterProxy類注冊(以SessionRepositoryFilter bean命名,名為“ springSessionRepositoryFilter”)不同的一件事是,您將DelegatingFilterProxy.class傳遞為servletContext.addFilter("filterName", <FilterType>); ,如下所示...

FilterRegistration.Dynamic springSessionRepositoryFilter = 
    container.addFilter("springSessionRepositoryFilter", DelegatingFilterProxy.class);

但是, Spring Session (核心)本身實際上會構造並初始化 (使用“ springSessionRepositoryFilter” bean名稱)Spring DelegatingFilterProxy類的實例, 並將該“實例” 傳遞給注冊時的ServletContext.addFilter(..)方法(第二個參數)。 。

我懷疑ServletContext.addFilter(..) API本身在構造/初始化實例時僅使用Spring DelegatingProxyFilter類的默認構造函數,這可能是問題的根源,尤其是在以編程方式注冊Servlet Filter時。

值得深思。

希望這可以幫助!

試用建議后,問題仍然存在。 現在,我們不再為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的顯式注冊。

當我們查看堆棧跟蹤時,可以看到該過濾器首先被調用。 因此,篩選器鏈的順序似乎是完整的。

我們面臨問題的過濾器隨后被調用。 即使沒有提及的更改,這也是相同的行為。

盡管如此,過濾器中的會話對象還是來自容器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM