谷粒商城实战笔记-229-商城业务-认证服务-SpringSession原理

Spring Session 原理概述

Spring Session 是 Spring Framework 的一部分,它提供了一种灵活的方式来管理分布式环境中的 HTTP Session。Spring Session 的核心思想是将 Session 数据从单个应用服务器中抽离出来,存储在一个集中的地方,如 Redis、Memcached 或数据库等,从而解决了分布式环境中 Session 共享的问题。

下面将结合源码简要介绍 Spring Session 的关键组件和工作原理。

关键组件

  1. HttpSessionStrategy:这是一个接口,定义了如何处理 HTTP Session 的创建、更新和销毁等操作。
  2. AbstractHttpSessionStrategy:这是一个抽象类,实现了 HttpSessionStrategy 接口的基本功能,为具体的 Session 策略提供了基础实现。
  3. RedisOperationsSessionRepository:这是一个具体的 Session 存储实现,使用 Redis 作为后端存储。
  4. DefaultCookieSerializer:用于序列化和反序列化 HTTP Cookie。
  5. DefaultCookieGenerator:生成 Cookie 的策略。
  6. DefaultSessionIdResolver:用于解析客户端传来的 Session ID。
  7. DefaultSessionIdCreator:用于创建新的 Session ID。
  8. SessionRepositoryFilter:这是一个过滤器,用于拦截请求并处理 Session 的逻辑。

工作流程

  1. 初始化配置

    • 用户配置 Spring Session 的相关 Bean,如 CookieSerializerRedisSerializer
    • Spring Session 会根据配置创建 SessionRepository 实例,如 RedisOperationsSessionRepository
  2. 请求处理

    • 当客户端发送请求时,SessionRepositoryFilter 会拦截该请求。
    • SessionRepositoryFilter 通过 DefaultSessionIdResolver 获取客户端传来的 Session ID。
    • 如果客户端没有提供 Session ID(首次访问或 Session 过期),则 DefaultSessionIdCreator 会创建一个新的 Session ID。
    • SessionRepositoryFilter 通过 SessionRepository 从 Redis 中加载或创建一个新的 Session。
    • Session 被封装为 DefaultSession 对象,并与请求关联起来。
  3. Session 操作

    • 控制器可以像使用标准的 HttpSession 一样使用 DefaultSession
    • 对 Session 的任何修改都会被记录下来,以便稍后保存到 Redis 中。
  4. Session 保存

    • 当请求结束时,SessionRepositoryFilter 会检测到 Session 是否有变更。
    • 如果 Session 有变更,则会调用 SessionRepositorysave 方法将 Session 保存到 Redis 中。
    • 如果 Session 没有变更,则不会执行保存操作。
  5. Session 无效

    • 如果 Session 过期或被标记为无效,SessionRepository 会将其从 Redis 中删除。

源码分析

1. SessionRepositoryFilter

SessionRepositoryFilter 是 Spring Session 中的关键过滤器,它负责处理 Session 的创建、加载、保存和删除等操作。

public class SessionRepositoryFilter extends OncePerRequestFilter {
    // ...

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
            FilterChain filterChain) throws ServletException, IOException {
        
        HttpSession session = null;
        boolean sessionCreated = false;
        try {
            // 1. 从请求中获取 Session ID
            String sessionId = this.sessionIdResolver.resolveSessionId(request);

            if (sessionId == null) {
                // 2. 如果没有 Session ID,则创建一个新的 Session ID
                sessionId = this.sessionIdCreator.createSessionId(request, response);
            }

            // 3. 从 SessionRepository 加载或创建 Session
            session = this.sessionRepository.getSession(sessionId, true);

            // 4. 将 Session 与请求绑定
            bindSessionToRequest(request, session);

            // 5. 继续执行过滤器链
            filterChain.doFilter(request, response);

            // 6. 检查 Session 是否发生了变更
            if (session.isNew()) {
                sessionCreated = true;
            } else if (this.sessionRepository.isChanged(session)) {
                sessionCreated = true;
            }

            // 7. 如果 Session 发生了变更,则保存 Session
            if (sessionCreated) {
                saveSession(session, response);
            }
        } finally {
            // 8. 清理 Session 与请求的绑定
            unbindSessionFromRequest(request, session);
        }
    }

    // ...
}
2. RedisOperationsSessionRepository

RedisOperationsSessionRepository 是一个具体的 SessionRepository 实现,用于与 Redis 进行交互。

public class RedisOperationsSessionRepository implements SessionRepository<DefaultSession> {
    // ...

    @Override
    public DefaultSession createSession() {
        // 创建一个新的 Session
        DefaultSession session = new DefaultSession(this, this.defaultMaxInactiveIntervalInSeconds);
        session.setAttribute(CREATED_TIME_ATTRIBUTE_NAME, System.currentTimeMillis());
        return session;
    }

    @Override
    public DefaultSession getSession(String id, boolean create) {
        // 从 Redis 中加载 Session
        DefaultSession session = loadSession(id);
        if (session == null && create) {
            // 如果不存在且允许创建,则创建新的 Session
            session = createSession();
        }
        return session;
    }

    @Override
    public void save(DefaultSession session) {
        // 保存 Session 到 Redis
        if (session.isNew()) {
            this.redisTemplate.opsForValue().set(this.keyPrefix + session.getId(), session, session.getMaxInactiveIntervalInSeconds(), TimeUnit.SECONDS);
        } else {
            this.redisTemplate.opsForValue().set(this.keyPrefix + session.getId(), session, session.getMaxInactiveIntervalInSeconds(), TimeUnit.SECONDS);
        }
    }

    // ...
}
3. DefaultSession

DefaultSession 是 Spring Session 中的一个具体 Session 实现,它继承自 AbstractHttpSession 并实现了 HttpSession 接口。

public class DefaultSession extends AbstractHttpSession {
    // ...

    @Override
    public void setAttribute(String name, Object value) {
        super.setAttribute(name, value);
        // 标记 Session 为已变更
        this.changed = true;
    }

    @Override
    public void removeAttribute(String name) {
        super.removeAttribute(name);
        // 标记 Session 为已变更
        this.changed = true;
    }

    // ...
}

总结

Spring Session 通过一系列组件和策略来管理分布式环境中的 Session。它利用过滤器拦截请求,通过 Session 存储策略(如 Redis)来处理 Session 的创建、加载和保存。这样,不仅解决了分布式环境下 Session 共享的问题,还保证了应用的可伸缩性和高可用性。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
根据引用中提供的信息,谷粒商城是一个B2C模式的电商平台,主要销售自营商品给客户。B2C模式指的是商对客的模式,即商家直接向消费者销售商品和服务谷粒商城使用微服务架构,这是一种将应用程序拆分成独立且可独立开发、部署和扩展的小型服务的架构。引用还提到谷粒商城的技术涵盖微服务架构、分布式、全栈、集群、部署和自动化运维等方面。 因此,从前慢-谷粒商城篇章6主要讨论的可能是谷粒商城的技术方面,包括微服务架构、分布式、全栈、集群、部署和自动化运维等内容。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [从前慢-谷粒商城篇章1](https://blog.csdn.net/m0_67391121/article/details/125383572)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [2020年谷粒商城md笔记](https://download.csdn.net/download/ZHUXIUQINGIT/12543161)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小手追梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值