После использования фильтра объекта сеанса spring-session-jdbc пустой в последующем CompositeFilter - PullRequest
0 голосов
/ 08 мая 2019

Проблема Опишите (кажется, проблема синхронизации):

После использования SpringSessionRepositoryFilter объект сеанса пуст во время период обработки OtherFilter в начале каждого запроса

Что я пробовал:

  • В контроллере и JSP после OtherFilter объект сеанса не пуст и работает нормально
  • Без использования springSessionRepositoryFilter объект сеанса notempty и отлично работает в OtherFilter

Конфигурация указана ниже:

<bean class="org.springframework.web.filter.CompositeFilter" name="springChainFilter">
    <property name="filters">
        <list>
            <bean id="springSessionRepositoryFilter" class="org.springframework.session.web.http.SessionRepositoryFilter">
            </bean>

            <!--Other Later Filter -->
            <bean id="otherFilter" class="xxx.xxx.OtherFilter">
            </bean>
        </list>
    </property>
</bean>

<bean class="org.springframework.session.jdbc.config.annotation.web.http.JdbcHttpSessionConfiguration"/>

<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <constructor-arg ref="dataSource"/>
</bean>

<bean id="cookieSerializer" class="org.springframework.session.web.http.DefaultCookieSerializer">
    <property name="cookieName" value="JSESSIONID" />
</bean>

Определение другого фильтра приведено ниже:

public class OtherFilter extends OncePerRequestFilter {


    @Autowired
    private SessionObj sessionObj;

    ......
}

Определение объекта сеанса выглядит следующим образом:

@Component
@SessionScope
public class SessionObj implements Serializable {

    private static final long serialVersionUID = 1L;


    private String xxId;

    ......
}

Информация о версии среды:

  • spring-session-jdbc-2.1.5.RELEASE
  • wildfly-11.0.0. Финал
  • Oracle Database 18c Express Edition, выпуск 18.0.0.0.0

Ответы [ 2 ]

0 голосов
/ 06 июня 2019

Другое решение для этого вопроса

Добавьте requestContextFilter между springSessionRepositoryFilter и otherFilter

<bean class="org.springframework.web.filter.CompositeFilter" name="springChainFilter">
    <property name="filters">
        <list>
            <bean id="springSessionRepositoryFilter" class="org.springframework.session.web.http.SessionRepositoryFilter">
            </bean>
            <!--Request Context Filter -->
            <bean id="requestContextFilter" class="org.springframework.web.filter.RequestContextFilter" />
            <!--Other Later Filter -->
            <bean id="otherFilter" class="xxx.xxx.OtherFilter">
            </bean>
        </list>
    </property>
</bean>

In RequestContextFilter (применяется для пружинных рамок)

  • wrappedRequest предоставляется текущему потоку через оба LocaleContextHolder и RequestContextHolder
  • [requestAttributes] связан с экземпляром SessionRepositoryRequestWrapper (делать что-то вроде FrameworkSevlet в будущее)
0 голосов
/ 03 июня 2019

Причина этого вопроса

  • @ SessionObj с автопроводкой в ​​OtherFilter
  • @ SessionObj с автопроводкой в ​​контроллере после OtherFilter

Обе ситуации выше, источником DI является запрос # getsession (), который привязан к объекту [requestAttributes].

org.springframework.web.context.request.ServletRequestAttributes

    protected final HttpSession getSession(boolean allowCreate) {
        if (isRequestActive()) {
            HttpSession session = this.request.getSession(allowCreate);
            this.session = session;
            return session;
        }
    }

Ниже приведены основные этапы во время одного запроса:

последовательность от а до е

а. В RequestContextListner

  • объект [requestAttributes] связан с экземпляром HttpServletRequestImpl (без информации о сеансе из БД)

    org.springframework.web.context.request.RequestContextListener

    public void requestInitialized(ServletRequestEvent requestEvent) {
        if (!(requestEvent.getServletRequest() instanceof HttpServletRequest)) {
            throw new IllegalArgumentException(
                    "Request is not an HttpServletRequest: " + requestEvent.getServletRequest());
        }
        HttpServletRequest request = (HttpServletRequest) requestEvent.getServletRequest();
        ServletRequestAttributes attributes = new ServletRequestAttributes(request);
        request.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes);
        LocaleContextHolder.setLocale(request.getLocale());
        RequestContextHolder.setRequestAttributes(attributes);
    }
    

б. В SessionRepositoryFilter

  • запрос заключен в SessionRepositoryRequestWrapper (с сеансом информация из БД)
  • но объект [requestAttributes] не переименован с экземпляром SessionRepositoryRequestWrapper

    org.springframework.session.web.http.SessionRepositoryFilter

    protected void doFilterInternal(HttpServletRequest request,
            HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        request.setAttribute(SESSION_REPOSITORY_ATTR, this.sessionRepository);
    
        SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(
                request, response);
        SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(
                wrappedRequest, response);
    
        try {
            filterChain.doFilter(wrappedRequest, wrappedResponse);
        }
    }
    

с. В другом фильтре

  • SessionObj внедряется через [requestAttributes], связанный с экземпляр HttpServletRequestImpl (без информации о сеансе из БД), поэтому пусто
* * +1058 д. В FrameworkServlet
  • объект [requestAttributes] повторно привязан с экземпляром SessionRepositoryRequestWrapper (с информацией о сеансе из БД), который был завернутый в предыдущий процесс b

    org.springframework.web.servlet.FrameworkServlet

    protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
    
        ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
        initContextHolders(request, localeContext, requestAttributes);
        }
    
    private void initContextHolders(HttpServletRequest request,
            @Nullable LocaleContext localeContext, @Nullable RequestAttributes requestAttributes) {
    
        if (requestAttributes != null) {
            RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
        }
    
    }
    

е. В контроллере после OtherFilter

  • SessionObj внедряется через [requestAttributes], связанный с экземпляр SessionRepositoryRequestWrapper (с информацией о сеансе из БД), так что отлично работает

Одно решение для этого вопроса

Добавление фильтра получения сеанса между springSessionRepositoryFilter и другой фильтр

<bean class="org.springframework.web.filter.CompositeFilter" name="springChainFilter">
    <property name="filters">
        <list>
            <bean id="springSessionRepositoryFilter" class="org.springframework.session.web.http.SessionRepositoryFilter">
            </bean>
            <!--Session Retrieve Filter -->
            <bean id="sessionRetrieveFilter" class="xxx.xxx.SessionRetrieveFilter">
            <!--Other Later Filter -->
            <bean id="otherFilter" class="xxx.xxx.OtherFilter">
            </bean>
        </list>
    </property>
</bean>

В Session Retrieve Filter свяжите [requestAttributes] с экземпляр SessionRepositoryRequestWrapper (сделать что-то вроде FrameworkSevlet сделать в будущем)

xxx.xxx.SessionRetrieveFilter

    protected void doFilterInternal(HttpServletRequest request,
            HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        RequestAttributes wrappedAttributes = new ServletRequestAttributes(request, response);
        RequestContextHolder.setRequestAttributes(wrappedAttributes);

        filterChain.doFilter(request, response);
    } 
...