The principle Spring Session solve the problem of distributed Session


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.xmlthe 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

Write pictures described here

Tell us about DelegatingFilterProxy this class:

DelegatingFilterProxy Class by springSessionRepositoryFilter name to look up configuration Bean Spring container and a filter converter, calls for DelegatingFilterProxyeach 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

Write pictures described here

我们在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

Write pictures described here

(2)RedisHttpSessionConfiguration主要方法和属性如下:

Write pictures described here

(3)RedisHttpSessionConfiguration通过@Bean的方式将RedisMessageListenerContainer、RedisTemplate、RedisOperationsSessionRepository 等注入到Spring容器中。

(4)RedisHttpSessionConfiguration继承了SpringHttpSessionConfiguration这个类,这个类很重要,SpringHttpSessionConfiguration通过@Bean的方式将springSessionRepositoryFilter注入到容器中:

Write pictures described here

springSessionRepositoryFilter这个过滤器就是前边DelegatingFilterProxy查找的过滤器!

(6)可以看出他是SessionRepositoryFilter类型的,SessionRepositoryFilter的作用就是替换容器默认的javax.servlet.http.HttpSession支持为org.springframework.session.Session。

SessionRepositoryFilter的主要方法和属性如下:

Write pictures described here

(7)其中SessionRepositoryResponseWrapper、SessionRepositoryRequestWrapper、HttpSessionWrapper为内部类,这个也是很关键的。例如SessionRepositoryRequestWrapper类:

Write pictures described here

可以看出SessionRepositoryRequestWrapper继承了javax.servlet.http.HttpServletRequestWrapper这个类,我们知道HttpServletRequest接口的默认实现是有HttpServletRequestWrapper的,如下:

Write pictures described here

(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代码如下:

Write pictures described here

(2)查看效果:

Write pictures described here

我们通过快捷键查看request.getSession() 的具体实现,就可以看出已经有了SessionRepositoryRequestWrapper 重写的方法。

上述有两个默认的实现,一个是原始的,一个是Spring Session实现的,具体选用哪一种作为实现,这就是我们上边说的DelegatingFilterProxy 代理的作用了,他会将每一个请求过滤,经过DelegatingFilterProxy的每一个请求也会经过springSessionRepositoryFilter过滤器,springSessionRepositoryFilter过滤器就实现了将原有request到SessionRepositoryRequestWrapper的转换,这就是实现了具体的流程!

(3)request.getSession().setAttribute(name, value)的实现:

追踪代码,可以到达下边内容

Write pictures described here

this.session.setAttribute(name, value) 中session是Session接口的定义,具体实现有:

Write pictures described here

可以看到有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

Guess you like

Origin blog.csdn.net/jxz999000/article/details/80507860