Сеансовый объект контейнера, а не сессионный объект GemFire ​​вызывается внутри фильтра сервлетов - PullRequest
0 голосов
/ 12 сентября 2018

Из пользовательского фильтра сервлетов при попытке получить доступ к объекту сеанса 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 был не добавлен в цепочку фильтров, нам пришлось явно зарегистрировать фильтр с помощью 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 работает абсолютно нормально, как задумано.Но вызов того же самого из фильтра сервлетов в конечном итоге приводит к созданию объекта сеанса, созданного контейнером.

Любая помощь приветствуется.

Переработано в соответствии с комментарием @John Blum, но все еще сталкивается с той же проблемой.

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

Проблема все еще сохраняется после опробования предложений. Теперь мы больше не используем отдельную регистрацию для 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.

Мы могли видеть, что этот фильтр вызывается первым, когда мы смотрим на трассировку стека. Таким образом, порядок цепочки фильтров выглядит нетронутым.

Фильтр, в котором мы сталкиваемся с проблемой, вызывается впоследствии. Это было то же самое поведение даже без упомянутых изменений.

Тем не менее, объект сеанса в фильтре взят из контейнера.

0 голосов
/ 12 сентября 2018

В двух словах, для Весенний сеанс и, в частности, Весенний сеанс для Pivotal GemFire ​​ (SSDG), дочтобы выполнить свою работу, SessionRepositoryFilter ( Javadoc , Source ) должен быть первым фильтром сервлетов в цепочке фильтров при регистрации в вашем (Web) контейнере приложений(например, Apache Tomcat, Eclipse Jetty и т. д.).

В противном случае, если Spring Session's SessionRepositoryFilter не является первым фильтром сервлетов в цепочке фильтров, тогда Spring Session не будет перехватывать HTTP-запрос (пока) и не сможет воспользоваться возможностью заменить сеанс контейнера (обернув HttpServletRequest на SessionRepositoryFilter.SessionRepositoryRequestWrapper, см. здесь ) на Session предоставляется Spring Session с использованием соответствующего провайдера (например, как GemFire ​​с SSDG), как определено реализацией SessionRepository, которая установлена ​​на SessionRepositoryFilter ( здесь ).

Причиной работы вашего приложения Spring Web MVC Controller являетсяспецификация / контейнер сервлета Java EE гарантирует, что все фильтры сервлетов будут вызваны до вызова любых сервлетов с помощью HTTP-запроса (т. е. HttpServletRequest).И, поскольку Spring Web MVC DispatcherServlet является правильным HttpServlet и отвечает за вызов вашего Spring-MVC Controllers, определенного приложением, то приложение Controllers гарантированно увидит «замененный» HTTP-запрос (ипо сути, объект сеанса HTTP).

Итак, несколько вспомогательных элементов ... Я (точно) не уверен, что вы подразумеваете под:

  1. 2.0.5версия GemFire.2.0.5 относится к последней / текущей версии Весенний сеанс для Pivotal GemFire ​​.

  2. И webappinitializer?

Для # 2, вы имели в виду, что специально создали Spring WebApplicationInitializer для явной регистрации SessionRepositoryFilter вручную (как показано выше в вашем фрагменте кода)?

Знаете ли вы, что Spring Session уже предоставляет такой класс ... o.s.session.web.context.AbstractHttpServletApplicationInitializer.

Этот класс отвечает за регистрацию SessionRepositoryFilter используя класс Spring DelegatingFilterProxy ( здесь , затем здесь и здесь (обратите внимание на переменную экземпляра insertBeforeOtherFilters, которая по умолчанию true),и в правильном порядке, здесь , в частности, здесь ).

Интересно, что кажется, что вы делаете то же самое или подобное вприведенный выше фрагмент кода фильтра.

ПРИМЕЧАНИЕ. Это (программная конфигурация контейнера Servlet) работает только в контейнерах Servlet 3.0.и позже.

Вы можете увидеть, как Spring Session's AbstractHttpServletApplicationInitializer используется в samples , например, здесь .Более подробную информацию о Initializer можно найти в соответствующих справочных документах для образца.

В регистрации класса Spring DelegatingFilterProxy (названной в честь компонента SessionRepositoryFilter, названного по-разному)Я заметил, что "springSessionRepositoryFilter") вы передаете DelegatingFilterProxy.class в качестве второго аргумента servletContext.addFilter("filterName", <FilterType>);, как показано здесь ...

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

Однако Spring Session (ядро) на самом деле создает и инициализирует (с именем бина "springSessionRepositoryFilter") экземпляр класса Spring DelegatingFilterProxy, а передает этот "экземпляр" в ServletContext.addFilter(..)метод (2-й аргумент) при регистрации.

Я подозреваю, что сам API ServletContext.addFilter(..) просто использует конструктор по умолчанию класса Spring DelegatingProxyFilter при создании / инициализации экземпляра, который, вероятно, является причиной вашей проблемы,особенно при программной регистрации фильтра сервлетов.

Пища для размышлений.

Надеюсь, это поможет!

...