Reprinted: http: //blog.csdn.net/xlgen157387/article/details/60321984
Previous:
Use Spring Session and Session Redis solve cross-domain distributed shared problem :
http://blog.csdn.net/xlgen157387/article/details/57406162
Previous describes how to use the Spring Session and Redis solve cross-domain sharing distributed Session, we introduced a simple case, below you learn about the Spring Session of the realization of the principle.
NOTE: The following steps are realized Spring Session XML-based code to explain the way!
Start talking about web.xml file
We know that when restarting Tomcat will first go to load the web.xml
file, Tomcat starts when web.xml
the order is loaded: context-param -> listener -> filter -> servlet
.
When we use the Spring Session, we configured a filter, configuration code is as follows:
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
Tell us about DelegatingFilterProxy
this class:
DelegatingFilterProxy
Class by springSessionRepositoryFilter
name to look up configuration Bean Spring container and a filter converter, calls for DelegatingFilterProxy
each request, this filter will be called springSessionRepositoryFilter.
如果未指定init-param
参数的话,DelegatingFilterProxy
就会把filter-name
作为要查找的Bean对象,这也是DelegatingFilterProxy
类的作用。可以看出每一个请求都会经过该filter,经过该filter的请求也会相应的经过springSessionRepositoryFilter
这个过滤器,那么我们就接着看一下springSessionRepositoryFilter
这个过滤器。
springSessionRepositoryFilter过滤器的创建
上一过程的DelegatingFilterProxy是从Spring容器中去查找springSessionRepositoryFilter的,那么我们是在哪个地方进行注入springSessionRepositoryFilter的哪?答案是在这里:
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>
- 1
- 1
我们在Spring的配置文件中手动注入了RedisHttpSessionConfiguration,这是因为我们默认的使用redis进行存储Session的。
RedisHttpSessionConfiguration 这个类加了Configuration注解,作为配置文件注入。
RedisHttpSessionConfiguration的作用是创建名为springSessionRepositoryFilter 的Spring Bean,继承自Filter。springSessionRepositoryFilter替换容器默认的HttpSession支持为Spring Session,将Session实例存放在Redis中。
(1)RedisHttpSessionConfiguration 继承关系如下:
@Configuration
@EnableScheduling
public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguration
implements EmbeddedValueResolverAware, ImportAware {
}
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
(2)RedisHttpSessionConfiguration主要方法和属性如下:
(3)RedisHttpSessionConfiguration通过@Bean的方式将RedisMessageListenerContainer、RedisTemplate、RedisOperationsSessionRepository
等注入到Spring容器中。
(4)RedisHttpSessionConfiguration继承了SpringHttpSessionConfiguration这个类,这个类很重要,SpringHttpSessionConfiguration通过@Bean的方式将springSessionRepositoryFilter注入到容器中:
springSessionRepositoryFilter这个过滤器就是前边DelegatingFilterProxy查找的过滤器!
(6)可以看出他是SessionRepositoryFilter类型的,SessionRepositoryFilter的作用就是替换容器默认的javax.servlet.http.HttpSession支持为org.springframework.session.Session。
SessionRepositoryFilter的主要方法和属性如下:
(7)其中SessionRepositoryResponseWrapper、SessionRepositoryRequestWrapper、HttpSessionWrapper为内部类,这个也是很关键的。例如SessionRepositoryRequestWrapper类:
可以看出SessionRepositoryRequestWrapper继承了javax.servlet.http.HttpServletRequestWrapper这个类,我们知道HttpServletRequest接口的默认实现是有HttpServletRequestWrapper的,如下:
(8)因为SessionRepositoryRequestWrapper继承了HttpServletRequestWrapper,而HttpServletRequestWrapper实现了HttpServletRequest接口,在SessionRepositoryRequestWrapper又重写了HttpServletRequest接口中的一些方法,所以才会有:getSession、changeSessionId等这些方法。
到此,我们应该大致明白了,原有的request请求和response都被重新进行了包装。我们也就明白了原有的HttpSeesion是如何被Spring Session替换掉的。
需要注意的是:
The SessionRepositoryFilter must be placed before any Filter that access the HttpSession or that might commit the response to ensure the session is overridden and persisted properly.
- 1
- 1
案例分析
(1)Controller代码如下:
(2)查看效果:
我们通过快捷键查看request.getSession()
的具体实现,就可以看出已经有了SessionRepositoryRequestWrapper
重写的方法。
上述有两个默认的实现,一个是原始的,一个是Spring Session实现的,具体选用哪一种作为实现,这就是我们上边说的DelegatingFilterProxy
代理的作用了,他会将每一个请求过滤,经过DelegatingFilterProxy的每一个请求也会经过springSessionRepositoryFilter过滤器,springSessionRepositoryFilter过滤器就实现了将原有request到SessionRepositoryRequestWrapper的转换,这就是实现了具体的流程!
(3)request.getSession().setAttribute(name, value)的实现:
追踪代码,可以到达下边内容
this.session.setAttribute(name, value) 中session是Session接口的定义,具体实现有:
可以看到有Redis相关的操作!
At this point, we should be clear, the principle of the Spring Session! Although the process did not go below the introduction, but has been very clear understanding of the