Session与Redis的结合,spring-session-

2022-01-19  本文已影响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

上一篇下一篇

猜你喜欢

热点阅读