工作纪实_22-搭建分布式项目时使用spring-session替代token

注册,设置的存储配置、机制和模式
@Beanpublic RedisIndexedSessionRepository sessionRepository() {RedisTemplate redisTemplate = createRedisTemplate();RedisIndexedSessionRepository sessionRepository = new RedisIndexedSessionRepository(redisTemplate);sessionRepository.setApplicationEventPublisher(this.applicationEventPublisher);if (this.indexResolver != null) {sessionRepository.setIndexResolver(this.indexResolver);}if (this.defaultRedisSerializer != null) {sessionRepository.setDefaultSerializer(this.defaultRedisSerializer);}sessionRepository.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);if (StringUtils.hasText(this.redisNamespace)) {sessionRepository.setRedisKeyNamespace(this.redisNamespace);}sessionRepository.setFlushMode(this.flushMode);sessionRepository.setSaveMode(this.saveMode);int database = resolveDatabase();sessionRepository.setDatabase(database);this.sessionRepositoryCustomizers.forEach((sessionRepositoryCustomizer) -> sessionRepositoryCustomizer.customize(sessionRepository));return sessionRepository;}
二、启动成功后,接受处理URL请求
ter重写apper的()方法
初始化
@Overridepublic RedisSession createSession() {MapSession cached = new MapSession();if (this.defaultMaxInactiveInterval != null) {cached.setMaxInactiveInterval(Duration.ofSeconds(this.defaultMaxInactiveInterval));}RedisSession session = new RedisSession(cached, true);session.flushImmediateIfNecessary();return session;}
【工作纪实_22-搭建分布式项目时使用spring-session替代token】public final class MapSession implements Session, Serializable {/*** Default {@link #setMaxInactiveInterval(Duration)} (30 minutes).*/public static final int DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS = 1800;private String id;private final String originalId;private Map, Object> sessionAttrs = new HashMap<>();private Instant creationTime = Instant.now();private Instant lastAccessedTime = this.creationTime;/*** Defaults to 30 minutes.*/private Duration maxInactiveInterval = Duration.ofSeconds(DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);/*** Creates a new instance with a secure randomly generated identifier.*/public MapSession() {this(generateId());}private static String generateId() {return UUID.randomUUID().toString();}}
至此,大致可以知道其实就是UUID的值,有兴趣的可以debug验证
问题:如果已经创建,那么分布式服务器如何知道用户已经登录了呢?
再回到ter的()方法
关注S= ();方法
逻辑一:为null
直接走创建()方法,即生成一个uuid的主键的对象
逻辑二:不为null
@Overridepublic HttpSessionWrapper getSession(boolean create) {HttpSessionWrapper currentSession = getCurrentSession();if (currentSession != null) {return currentSession;}S requestedSession = getRequestedSession();......省略部分代码.....S session = SessionRepositoryFilter.this.sessionRepository.createSession();session.setLastAccessedTime(Instant.now());currentSession = new HttpSessionWrapper(session, getServletContext());setCurrentSession(currentSession);return currentSession;}
我们从S= ();方法开始,一直追踪进去,会发现,实际生效的方法是在zer里面,也就是说,请求所在的客户端,是存在用户登录的信息的,请求过来的时候,浏览器会去请求携带的中获取,然后进行的解析!
private S getRequestedSession() {if (!this.requestedSessionCached) {##########注意啦,这里是服务器解析请求中的cookie信息,解析session啦#############List> sessionIds = SessionRepositoryFilter.this.httpSessionIdResolver.resolveSessionIds(this);#####拿到请求sessionId之后,利用sessionRepository[redis]来对比对,匹配中一个,说明在线#######for (String sessionId : sessionIds) {if (this.requestedSessionId == null) {this.requestedSessionId = sessionId;}S session = SessionRepositoryFilter.this.sessionRepository.findById(sessionId);if (session != null) {this.requestedSession = session;this.requestedSessionId = sessionId;break;}}this.requestedSessionCached = true;}return this.requestedSession;}