• 【SpringBoot集成Redis + Session持久化存储到Redis】


    目录

    SpringBoot集成Redis 

    1.添加 redis 依赖  

    2.配置 redis 

    3.手动操作 redis   

    Session持久化存储到Redis 

    1.添加依赖

    2.修改redis配置

    3.存储和读取String类型的代码  

    4.存储和读取对象类型的代码  

    5.序列化细节


    SpringBoot集成Redis 

    1.添加 redis 依赖  

    或将以下配置添加到 pom.xml 中:   


                org.springframework.boot
                spring-boot-starter-data-redis

    2.配置 redis 

    #redis地址
    spring.redis.host=x.x.x.x
    #端口号
    spring.redis.port=6379
    spring.redis.password=
    #DB[0-15]
    spring.redis.database=0 
    # 可省略
    spring.redis.lettuce.pool.min-idle=5
    spring.redis.lettuce.pool.max-idle=10
    spring.redis.lettuce.pool.max-active=8
    spring.redis.lettuce.pool.max-wait=1ms
    spring.redis.lettuce.shutdown-timeout=100ms 

    3.手动操作 redis   

    1. @RestController
    2. public class RedisController {
    3. @Autowired
    4. private StringRedisTemplate stringRedisTemplate;
    5. // 在 redis 存储数据 30s之后自动失效
    6. @RequestMapping("/set")
    7. public String set(String name, String value) {
    8. stringRedisTemplate.opsForValue().set(name, value, 30, TimeUnit.SECONDS);
    9. return "Set redis success.";
    10. }
    11. // 读取 redis 中的数据
    12. @RequestMapping("/get")
    13. public String get(String name) {
    14. Object valObj = stringRedisTemplate.opsForValue().get(name);
    15. if (valObj != null) {
    16. return valObj.toString();
    17. }
    18. return "Null";
    19. }
    20. }

    通过postman发送请求测试: 

    下面测试存入字典(Hash)类型: 

    1. // 在 redis 存储数据
    2. @RequestMapping("/set2")
    3. public String set2() {
    4. stringRedisTemplate.opsForHash().put("myhash","name","ws");
    5. return "Set redis success.";
    6. }
    7. // 读取 redis 中的数据
    8. @RequestMapping("/get2")
    9. public String get2() {
    10. Object valObj = stringRedisTemplate.opsForHash().get("myhash", "name");
    11. if (valObj != null) {
    12. return valObj.toString();
    13. }
    14. return "Null";
    15. }

    Session持久化存储到Redis 

    1.添加依赖

    或者在pom.xml中引入: 



                org.springframework.boot
                spring-boot-starter-web

    2.修改redis配置

    # 设置连接的Redis数据库的索引。默认情况下,索引为0,即连接到默认的数据库。
    # 如果设置多个Redis实例,可以通过此项进行区分。
    spring.redis.database=0
    # 设置连接的Redis服务器的主机名或IP地址
    spring.redis.host=x.x.x.x
    spring.redis.password=
    # 设置连接的Redis服务器的端口号。在此,服务器的端口号为6379,这是Redis默认的端口号,默认的话可以省略不写。
    spring.redis.port=6379
    # 设置会话存储类型为Redis
    spring.session.store-type=redis
    # 设置服务器上所有Servlet的会话超时时间为1800秒,即30分钟。
    # Spring Boot默认的会话超时时间为30分钟,但在这里,它被明确地设定为1800秒
    server.servlet.session.timeout=1800
    # 设置Redis的flush mode为'on_save'。flush mode决定了何时将数据写入磁盘。
    # 'on_save'意味着每次数据被保存时都会立即写入磁盘,这可以保证数据的持久性,但可能会影响性能。
    spring.session.redis.flush-mode=on_save
    # 设置Spring Session在Redis中的命名空间为'spring:session'。
    # 这是为了防止不同的应用在同一Redis实例中产生数据冲突。每个应用都可以使用不同的命名空间来保存自己的会话数据。
    spring.session.redis.namespace=spring:session

    3.存储和读取String类型的代码  

    1. @RestController
    2. @RequestMapping("/user")
    3. public class UserController {
    4. // user session key
    5. private static final String SESSION_KEY_USERINFO = "SESSION_KEY_USERINFO";
    6. @RequestMapping("/set")
    7. public String set(HttpSession session) {
    8. session.setAttribute(SESSION_KEY_USERINFO, "ws");
    9. return "ok";
    10. }
    11. @RequestMapping("/get")
    12. public String get(HttpServletRequest request) {
    13. HttpSession session = request.getSession(false);
    14. Object userObj = null;
    15. if (session != null && (userObj = session.getAttribute(SESSION_KEY_USERINFO)) != null) {
    16. return (String) userObj;
    17. }
    18. return "Null";
    19. }
    20. }

    通过postman进行测试:

    4.存储和读取对象类型的代码  

    实体类:

    1. @Data
    2. public class UserInfo {
    3. private int id;
    4. private String username;
    5. private int age;
    6. }

    controller类:

    1. @RestController
    2. @RequestMapping("/user")
    3. public class UserController {
    4. // user session key
    5. private static final String SESSION_KEY_USERINFO = "SESSION_KEY_USERINFO";
    6. @RequestMapping("/set")
    7. public String set(HttpSession session) {
    8. //...经过一系列的判断
    9. UserInfo userInfo = new UserInfo();
    10. userInfo.setId(1);
    11. userInfo.setUsername("ws");
    12. userInfo.setAge(18);
    13. session.setAttribute(SESSION_KEY_USERINFO, userInfo);
    14. return "ok";
    15. }
    16. @RequestMapping("/get")
    17. public UserInfo get(HttpServletRequest request) {
    18. HttpSession session = request.getSession(false);
    19. Object userObj = null;
    20. if (session != null && (userObj = session.getAttribute(SESSION_KEY_USERINFO)) != null) {
    21. return (UserInfo) userObj;
    22. }
    23. return null;
    24. }
    25. }

    通过postman测试:发现是序列化的问题 

    解决方案: 

    让UserInfo类实现序列化接口,同时生成序列化版本号。
    ps:凡是实现Serializable接口(标识接口)的类都有一个表示序列化版本标识符的静态常量:
    private static final long serialVersionUID;
    serialVersionUID用来表明类的不同版本间的兼容性。简言之,其目的是以序列化对象进行版本控制,有关各版本反序加化时是否兼容。
    如果类没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的实例变量做了修改,serialVersionUID 可能发生变化。故建议,显式声明。
    简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)

    设置生成序列化版本号: 

    在类上面ALT+ENTER: 

    再次测试: 

    5.序列化细节

    (1)被序列化的类的内部的所有属性,必须是可序列化的 (基本数据类型都是可序列化的
    (2)static,transient修饰的属性 不可以被序列化

    再测试下: 

    什么时候用static和transient?

    static类共享的时候
    transient:比如说银行卡的密码,不想被持久化(序列化),写到文件中假如被别人窃取了,别人可以通过反序列化把密码读出来(破解),需要保护的东西就可以用transient来修饰 

  • 相关阅读:
    【单片机毕业设计选题24005】-基于STM32的智能家居环境监测系统
    【Python】利用matplotlib在Pycharm中显示本地图片
    经典算法冒泡排序之标志位优化版
    使用 redis 减少 秒杀库存 超卖思路
    MySQL - Heap 表是什么?
    一口气拿下vue-router所有知识点,薪资暴涨3000
    golang 线程 定时器 --chatGPT
    超强的苹果官网滚动文字特效实现
    数据库设计原则
    Redis——其他数据类型介绍
  • 原文地址:https://blog.csdn.net/TheMyth142857/article/details/132867111