问题描述(似乎是计时问题):
使用SpringSessionRepositoryFilter后,会话对象在 每个请求开始时OtherFilter的处理时间
我尝试过的事情:
- 在Controller和JSP中,OtherFilter之后,会话对象不是空的并且可以正常工作
- 在不使用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>
<!--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>
OtherFilter定义如下:
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。发布
- wildfly-11.0.0.Final
- Oracle Database 18c Express Edition版本18.0.0.0.0
答案 0 :(得分:0)
此问题的原因
- @OtherFilter中的@Autowired SessionObj
- @OtherFilter之后在控制器中自动连接SessionObj
以上两种情况,DI的源都是request#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;
}
}
在一个请求中有以下里程碑:
从a到e的顺序
a。在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);
}
b。在SessionRepositoryFilter
但是,对象[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);
}
}
c。在OtherFilter
d。在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);
}
}
e。在Controller中OtherFilter之后
该问题的一个解决方案
在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>
在会话检索过滤器中,将[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);
}
答案 1 :(得分:0)
此问题的另一个解决方案
在springSessionRepositoryFilter和之间添加requestContextFilter 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>
在RequestContextFilter中(由spring框架应用)