美文网首页
Session与Redis的结合,spring-session-

Session与Redis的结合,spring-session-

作者: 程就人生 | 来源:发表于2022-01-19 22:42 被阅读0次

    现在越来越多的项目使用微服务分布式,那么对于分布式:

    session 该如何共享呢?

    spring-session-data-redis 框架就是来解决这个问题的。

    一、简单使用;

    1. 使用 IDEA 的 Spring Starter Project 新建一个带web的测试项目,打开pom文件,加入两个依赖:
    <!-- 引入 session与redis的集成 -->
            <dependency>
                <groupId>org.springframework.session</groupId>
                <artifactId>spring-session-data-redis</artifactId>
            </dependency>
            <!-- redis连接配置 -->
            <dependency>
                <groupId>io.lettuce</groupId>
                <artifactId>lettuce-core</artifactId>
            </dependency>
    
    2. 创建测试类 IndexController;
    package com.example.demo.controller;
    import javax.servlet.http.HttpServletRequest;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * 分布式测试session共享示例
     * @author 程就人生
     * @Date 2022-01-09
     */
    @RestController
    public class IndexController {
        /**
         * 设置session
         * @param request
         * @return
         */
        @GetMapping("/set")
        public Object Index(HttpServletRequest request){        
            request.getSession().setAttribute("userUid", "111111");
            return request.getSession().getAttribute("userUid");
        }
        
        /**
         * 获取session
         * @param request
         * @return
         */
        @GetMapping("/get")
        public Object Index1(HttpServletRequest request){
            return request.getSession().getAttribute("userUid");
        }   
    }
    
    3.测试session共享

    分别以端口8080、8081启动该项目;启动后,通过一个浏览器打开两个浏览器窗口;
    一个输入地址:http://localhost:8080/set

    测试结果

    另一个输入地址:http://localhost:8081/get

    测试结果
    4.查看redis里session的存储结构;

    从redis的客户端,可以看到关于session的详细信息:



    就是这么简单地实现了分布式session共享~!

    当然肯定有朋友会问:

    如果想更改session的过期日期,怎么改?

    如果想更改session存储在redis里的前缀,怎么改?

    二、关键注解 @EnableRedisHttpSession 分析;

    @EnableRedisHttpSession 源码查看;

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Documented
    @Import(RedisHttpSessionConfiguration.class)
    @Configuration(proxyBeanMethods = false)
    public @interface EnableRedisHttpSession {
    
        /**
         *  Session默认过期时间,单位为秒,默认30分钟
         */
        int maxInactiveIntervalInSeconds() default MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS;
    
        /**
         * Defines a unique namespace for keys.     
         *  配置session key的命名前缀,默认是spring
         */
        String redisNamespace() default RedisIndexedSessionRepository.DEFAULT_NAMESPACE;
    
        /**
         * Flush mode for the Redis sessions.   
         * In a web environment this happens just before the HTTP response is committed.     
         * Session are immediately written to the Redis instance.
             * 配置刷新Redis中Session的方式,默认是ON_SAVE模式,只有当Response提交后才会将Session提交到Redis
              * 也可以配置成IMMEDIATE模式,所有对Session的更改会立即更新到Redis
         */
        RedisFlushMode redisFlushMode() default RedisFlushMode.ON_SAVE;
    
        /**
            *  同 redisFlushMode
            */
        FlushMode flushMode() default FlushMode.ON_SAVE;
    
        /**
         * The cron expression for expired session cleanup job. 
             *  By default runs every minute.  "0 * * * * *"
             * 清理过期Session的定时任务默认一分钟一次
         */
        String cleanupCron() default RedisHttpSessionConfiguration.DEFAULT_CLEANUP_CRON;
    
        /**
         * 只有在更改的时候才进行保存;
         */
        SaveMode saveMode() default SaveMode.ON_SET_ATTRIBUTE;
    
    }
    

    源码分析:如果都使用默认配置,那么该注解可加可不加;
    如果想设置session过期时间,那么就可以在该注解上做调整;

    package com.example.demo;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.session.FlushMode;
    import org.springframework.session.MapSession;
    import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
    
    /**
     * @EnableRedisHttpSession 注解说明
     * @author 程就人生
     * @Date 2022-01-09
     */
    @EnableRedisHttpSession(maxInactiveIntervalInSeconds = MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS * 2, //1小时有效期
    redisNamespace = "myUser",  // 前缀为myUser
    flushMode = FlushMode.IMMEDIATE // 立即生效
    ) 
    @SpringBootApplication
    public class SpringSessionRedisApplication {
        public static void main(String[] args) {
            SpringApplication.run(SpringSessionRedisApplication.class, args);
        }
    }
    

    修改过了,测试一下,从下图中可以看到,redis的命名和过期时间都发生了改变;


    测试结果

    原理分析:该注解导入了 RedisHttpSessionConfiguration类,该类被注解了@Configuration,容器一启动里面的bean就会被加载:


    RedisHttpSessionConfiguration类又继承自 SpringHttpSessionConfiguration,在该类中通过 SessionRepositoryFilter 类 对所有的session进行了拦截:


    SessionRepositoryFilter 类,该类继承自 SessionRepositoryFilter :



    对所有的请求进行了拦截:


    最后总结

    主要的核心类:
    @EnableRedisHttpSession,配置注解,需要调整时再覆盖默认配置;
    RedisHttpSessionConfiguration,配置类,自动配置,开箱即用;
    SessionRepositoryFilter,拦截器,对HttpServletRequest、Response的拦截;
    RedisOperationsSessionRepository,在Redis中增删改查Session的功能;
    SessionRepositoryRequestWrapper,Request的包装类;
    SessionRepositoryResponseWrapper,Response的包装类。

    参考文档:
    https://docs.spring.io/spring-session/reference/guides/java-redis.html
    https://blog.csdn.net/qq_27088383/article/details/107767000

    相关文章

      网友评论

          本文标题:Session与Redis的结合,spring-session-

          本文链接:https://www.haomeiwen.com/subject/pgkqhrtx.html