SpringSession在分布式项目中的应用&原理描述

这里,我们选用spring session 的redis存储模式来解决分布式session的问题

一、整合与使用

1.引入依赖(注:前提是你的项目中要有 redis 依赖哦!)

  <!-- 整合springsession -->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

2.启动类中开启 springsession

@EnableRedisHttpSession     //开启springsession

3.在配置文件中指定springsession存储介质为redis

spring.session.store-type=redis

4.想要在多个子域名中都可以使用json的形式存储session,我们还需要对作用域和序列化方式进行配置

package com.xxx.xxx.product.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.DefaultCookieSerializer;

/**
 * @Description: springSession配置类
 * @Created: with IntelliJ IDEA.
 * @author: LY
 * @createTime: 2020-06-29 13:36
 **/

@Configuration
public class MySessionConfig {
    
    

    @Bean
    public CookieSerializer cookieSerializer() {
    
    

        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();

        //放大作用域,让session可以在各个子域名中读到
        cookieSerializer.setDomainName("xxx.com");
        //设置session-cookie名称
        cookieSerializer.setCookieName("XXSESSION");

        return cookieSerializer;
    }

    //让redis中的数据可以 用json形式存储
    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
    
    
        return new GenericJackson2JsonRedisSerializer();
    }

}

这里进行一下说明,我们的session在客户端记录成cookie时是有作用域的,比如你在 ss.xxx.com 生成的cookie ,里面存储的作用域就是 ss.xxx.com ,所以我们需要扩大他的作用域 为 ”.xxx.com“ 后,才能使各个子域名下的微服务进行session互通
如百度的:
在这里插入图片描述

5 . 正常使用session即可(示例)

	/**
	1.设置session 的 值****************************************
	**/
	//你的实体类
  	String userInfo= new UserInfo();
  	//转为接送字符串
  	String userInfoString = JSONObject.toJSONString(userInfo);
  	//1.设置session 的 值
	session.setAttribute("userInfo", userInfoString);
	

	/**
	2.获取session 的 值****************************************
	**/
    //2.获取session
    String userInfoSessionStr = session.getAttribute("userInfo");

二、核心原理

  1. 我们来看看 @EnableRedisHttpSession 注解中干了些什么
    在这里插入图片描述
    1.1 可以看到 导入了 RedisHttpSessionConfiguration.class 这个配置类

    a.进入到RedisHttpSessionConfiguration配置类中我们可以看到,首先他加载了RedisOperationsSessionRepository 这个组件,主要用于redis 持久层的增删改查操作。
    在这里插入图片描述
    b. 他还继承了一个配置类 SpringHttpSessionConfiguration
    在这里插入图片描述
    我们来看看这个继承的类里面干什么核心事情,核心就是他,里面有个SessionRepositoryFilter 过滤器
    在这里插入图片描述
    那这个 SessionRepositoryFilter 又是个什么呢? 进入到SessionRepositoryFilter 我们可以看到他继承了 OncePerRequestFilter,再往下追 OncePerRequestFilter ,OncePerRequestFilter 又 实现了 Filter, 这个 Filter 其实就是我们经常用到的过滤器,那我们就明白了,其实每一次的请求进来时都会被这个过滤器所捕捉到(SessionRepositoryFilter)
    在这里插入图片描述
    在这里插入图片描述
    c. 我们回到RedisHttpSessionConfiguration配置类中来看看 RedisOperationsSessionRepository 这个组件都有些什么方法(ALT+7 或者 CTRL+F12), 可以看到里面有很多session方法,与我们常用的session 操作方法是不是很像?对的,springsession就是通过这些方法来重写原session的curd方法后,来操作分布式session的。
    在这里插入图片描述
    d. 我们在来看 SessionRepositoryFilter ,里面有个重写方法 doFilterInternal ,其实核心就是他。
    可以看到里面有两个包装类:

//包装原始请求对象
SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(
				request, response, this.servletContext);
//包装原始响应对象
SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(
				wrappedRequest, response);
try {
    
    
			//将包装后的对象应用到我们后面的整个执行链中
			filterChain.doFilter(wrappedRequest, wrappedResponse);
		}
		finally {
    
    
			wrappedRequest.commitSession();
		}

在这里插入图片描述

e. 我们在使用session时一般是这样的。其中的session是由request.getSession()获得的,然而我们前面的一步中经过了过滤器其实HttpServletRequest 的session已经被包装过了,并且这里我们获得session方法getSession() 方法也是被重写过的,所以就完成了使用 redis 存储获取session的实现。

设计模式为:装饰着模式。

其他: springsession使用redis分布式session 其实也解决了我们session应用的所有问题,存储后默认过期时间为30分钟,只要我们浏览器不关闭,我们的session就会在redis中不断续期,直到我们的浏览器关闭。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/YL3126/article/details/120375042
今日推荐