简介
Spring Session 是Spring家族中的一个子项目,它提供一组API和实现,用于管理用户的session信息
它把servlet容器实现的httpSession替换为spring-session,专注于解决 session管理问题,Session信息存储在Redis中,key是由UUID生成,且以hash结构存放在redis,可简单快速且无缝的集成到我们的应用中;
Spring Session的特性:
- 提供用户session管理的API和实现
- 提供HttpSession,以中立的方式取代web容器的session,比如tomcat中的session
- 支持集群的session处理,不必绑定到具体的web容器去解决集群下的session共享问题
SSM中使用SpringSession
假设项目中已经配置号了redis,如若没有,请先参考ssm中集成redis
- maven依赖
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>1.3.1.RELEASE</version>
</dependency>
- 配置springSessionRepositoryFilter过滤器
<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>
</filter-mapping>
注意,放在所有过滤器之首,我是放在字符编码过滤器之后的。
- spring中配置spring-session
<!--定义SpringSession的配置Bean -->
<bean id="redisHttpSessionConfiguration" class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
<!--指定Cookie的序列化规则对象,用于改变SpringSessionCookie的存放规则 -->
<property name="cookieSerializer" ref="defaultCookieSerializer"/>
<!--设置Session的最大生命周期,单位为秒 默认有效期为1800 表示30分钟 -->
<!--<property name="maxInactiveIntervalInSeconds" value="1800"/>-->
</bean>
<!--自定义Cookie规则对象 -->
<bean id="defaultCookieSerializer" class="org.springframework.session.web.http.DefaultCookieSerializer">
<!--指定SpringSession的Cookie数据要存放到域名的根路径下,用于解决同域名下不同项目的Session共享 -->
<property name="cookiePath" value="/"/>
<!--指定SpringSession的Cookie数据要存放到根域名下,用于解决同根域名但是不同子域名的Session共享,
低版本的Tomcat(版本小于8)如果报错要在根域名前多加个点.-->
<property name="domainName" value="myweb.com"/>
</bean>
-
定义SpringSession的配置Bean:RedisHttpSessionConfiguration
a.指定Cookie的序列化规则对象参数
b.设置Session的最大生命周期 -
自定义Cookie规则对象:DefaultCookieSerializer,这里要注意两个参数(后台区分是否是同一个session和路径和域名有关)
a.解决同域名下不同项目的Session共享(Cookie的使用范围):设置 cookiePath 为域名的根路径
例如:现在有两个项目,分别是:localhost:8080/web1和localhost:9090/web2,通过浏览器提供的开发人员工具(F12–>Application–>Cookies–>SESSION)可以发现,这两个请求的cookie的路径(path)不一致,一个是/web1,一个是/web2,虽然我们已经加了SpringSession共享机制,但是后台服务器认为这是两个不同的会话(session),故需要指定 cookiePath 参数为 “/”b.解决同根域名但是不同子域名的Session共享:设置 domainName 为要存放的根域名
例如:还是上面的两个项目,只不过现在不再使用localhost了,而是使用域名,在C:\Windows\System32\drivers\etc\host文件中修改127.0.0.1的映射关系模拟不同的域名访问,这里使用的分别是:web1.web.com:8080/web1和web2.web.com:9090/web2,通过浏览器提供的开发人员工具可以发现,虽然这两个cookie的路径(path)都设置为了“/”,但是由于这两个cookie的域名(domain)不一致,虽然我们已经加了Spring Session共享机制,但是后台服务器同样认为这是两个不同的会话(session),故需要指定 domainName 参数为“web.com”
注意,需要在每个项目中都加入以上步骤的配置。
至此,SSM中配置spring-session完成!
我在项目中,实现根域名或者根路径,采用的是nginx配置,根据不同的请求,跳转到不同的项目,这样就实现了根路径一致,可以使用多个tomcat来部署不同的项目了。
SpringBoot配置Spring-Session
- 添加依赖
<!--spring连接redis的起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--springSession的依赖-->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
- 配置参数
#连接redis三要素:ip,端口,密码
spring.redis.host=192.168.29.128
spring.redis.port=6379
spring.redis.password=123456
#设置SessionId存放在Cookie中的什么路径中 /表示根路径,用于解决同域名下不同项目的Session共享
server.servlet.session.cookie.path=/
#设置SessionId存放在Cookie中的根域名,用于解决同根域名不同二级子域名的Session共享
server.servlet.session.cookie.domain=web.com
#设置Session的最大生命周期,默认值为30m 表示30分钟
server.servlet.session.timeout=30m
原理
- 页面请求被全局的过滤器org.springframework.web.filter.DelegatingFilterProxy过滤
- 全局的过滤器是一个代理过滤器,它不执行真正的过滤逻辑,它代理了一个Spring容器中的名为:springSessionRepositoryFilter
的一个过滤器 - 代理的这个 springSessionRepositoryFilter 过滤器是从spring容器中获取的,真正执行过滤逻辑的是
SessionRepositoryFilter - 该SessionRepositoryFilter过滤器覆盖了原来servlet中的request和response接口中定义的操作session方法,替换成自己的session方法
- 在过滤的时候,总是会执行一个finally语句块,在finally中提交session,保存到Redis的session以hash结构存放在redis中