springboot项目创建笔记22 之《spirng-session实现分布式session一致性》

spring-session组件可以自动将sessionId存入redis,解决分布式session一致性问题

1、pom文件添加依赖

<!-- spring session依赖 -->
<dependency>
	<groupId>org.springframework.session</groupId>
	<artifactId>spring-session-data-redis</artifactId>
</dependency>

2、添加配置类RedisSessionConfig.java

package com.example.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.data.redis.RedisFlushMode;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds= 3600*24, redisFlushMode = RedisFlushMode.ON_SAVE, redisNamespace = "redis:session")
public class RedisSessionConfig {
	/**
	 * 设置spring-session序列化类,替换默认JdkSerializationRedisSerializer
	 * @return
	 */
	@Bean
    RedisSerializer<Object> springSessionDefaultRedisSerializer() {
        return new GenericJackson2JsonRedisSerializer();
    }
}

3、添加RedisSessionController.java

package com.example.web;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@Api(description = "session一致性")
@RestController
@RequestMapping("/redisSession")
public class RedisSessionController {

	@ApiOperation("设置sessionId")
	@GetMapping("/setSessionId")
	public void setSession(HttpServletRequest request, HttpServletResponse response) {		
		//从请求中提取HttpSession对象
		HttpSession session = request.getSession();
		session.setAttribute("msg", "方法调用");
	}
	
	@ApiOperation("获取session属性")
	@GetMapping("/getSessionAttr")
	public String getSessionAttr(HttpServletRequest request, HttpServletResponse response) {
		//从请求中提取HttpSession对象
		HttpSession session = request.getSession();
		return (String)session.getAttribute("msg");
	}
}

4、运行测试方法

查看redis数据,添加了3条记录
1)Set数据类型
key为:redis:session:expirations:1612764840000
value为:"expires:c178a6d6-4378-4c61-8ec8-442715589e6d"
2)Hash数据类型
key为:redis:session:sessions:c178a6d6-4378-4c61-8ec8-442715589e6d
内容有4条:
hashKey为:lastAccessedTime,value为:1612677202861
hashKey为:maxInactiveInterval,value为:86400
hashKey为:creationTime,value为:1612676731746
hashKey为:sessionAttr:msg,value为:"方法调用"
3)String数据类型
key为:redis:session:sessions:expires:c178a6d6-4378-4c61-8ec8-442715589e6d

5、运行完一遍测试方法后,浏览器的cookie中会保存sessionId

 YzE3OGE2ZDYtNDM3OC00YzYxLThlYzgtNDQyNzE1NTg5ZTZk用base64解密之后就是,c178a6d6-4378-4c61-8ec8-442715589e6d

6、将redis中redis:session下的内容都删除,再次点击setSessionId,打断点观察

request、response、session三个对象,是经过SessionRepositoryFilter过滤器包装过的包装类
HttpServletRequest、HttpServletResponse、HttpSession都是客户端请求时由容器(比如tomcat)生成,传给服务端
在request对象中传了浏览器cookie中保存的sessionId:

在session对象中,由于redis中数据被删查找不到,生成了新的sessionId:

返回给浏览器新的sessionId:

set-cookie: SESSION=NTY3M2QyMzktNWU0ZS00Mzc3LTgzN2MtMzI3ZDViN2Y2OGIz; Path=/; HttpOnly; SameSite=Lax 
content-length: 0 
date: Sun, 07 Feb 2021 06:55:24 GMT

相同sessionId请求时:

7、@EnableRedisHttpSession注解参数说明
maxInactiveIntervalInSeconds():Session默认过期时间,单位秒,默认1800秒
redisNamespace():配置key的namespace,默认的是spring:session,如果不同的应用共用一个redis,应该为应用配置不同的namespace,这样才能区分这个Session是来自哪个应用的
redisFlushMode():配置刷新Redis中Session方式,默认是ON_SAVE模式,只有当Response提交后才会将Session提交到Redis,也可以配置成IMMEDIATE模式,即所有对Session的更改会立即更新到Redis
cleanupCron():清理过期Session的定时任务

参考资料:
https://blog.csdn.net/jsbylibo/article/details/106544932
https://blog.csdn.net/qq_43371556/article/details/100862785

注:最新代码上传至https://github.com/csj50/myboot
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值