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

2023-09-14 00:13:20

目录

SpringBoot集成Redis 

1.添加 redis 依赖  

2.配置 redis 

3.手动操作 redis   

Session持久化存储到Redis 

1.添加依赖

2.修改redis配置

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

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

5.序列化细节


SpringBoot集成Redis 

1.添加 redis 依赖  

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

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

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   

@RestController
public class RedisController {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    // 在 redis 存储数据  30s之后自动失效
    @RequestMapping("/set")
    public String set(String name, String value) {
        stringRedisTemplate.opsForValue().set(name, value, 30, TimeUnit.SECONDS);
        return "Set redis success.";
    }
    // 读取 redis 中的数据
    @RequestMapping("/get")
    public String get(String name) {
        Object valObj = stringRedisTemplate.opsForValue().get(name);
        if (valObj != null) {
            return valObj.toString();
        }
        return "Null";
    }
}

通过postman发送请求测试: 

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

    // 在 redis 存储数据
    @RequestMapping("/set2")
    public String set2() {
        stringRedisTemplate.opsForHash().put("myhash","name","ws");
        return "Set redis success.";
    }
    // 读取 redis 中的数据
    @RequestMapping("/get2")
    public String get2() {
        Object valObj = stringRedisTemplate.opsForHash().get("myhash", "name");
        if (valObj != null) {
            return valObj.toString();
        }
        return "Null";
    }

Session持久化存储到Redis 

1.添加依赖

或者在pom.xml中引入: 


<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
</dependency>

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类型的代码  

@RestController
@RequestMapping("/user")
public class UserController {
    // user session key
    private static final String SESSION_KEY_USERINFO = "SESSION_KEY_USERINFO";
    @RequestMapping("/set")
    public String set(HttpSession session) {
        session.setAttribute(SESSION_KEY_USERINFO, "ws");
        return "ok";
    }
    @RequestMapping("/get")
    public String get(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        Object userObj = null;
        if (session != null && (userObj = session.getAttribute(SESSION_KEY_USERINFO)) != null) {
            return (String) userObj;
        }
        return "Null";
    }
}

通过postman进行测试:

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

实体类:

@Data
public class UserInfo {
    private int id;
    private String username;
    private int age;
}

controller类:

@RestController
@RequestMapping("/user")
public class UserController {
    // user session key
    private static final String SESSION_KEY_USERINFO = "SESSION_KEY_USERINFO";
    @RequestMapping("/set")
    public String set(HttpSession session) {
        //...经过一系列的判断
        UserInfo userInfo = new UserInfo();
        userInfo.setId(1);
        userInfo.setUsername("ws");
        userInfo.setAge(18);
        session.setAttribute(SESSION_KEY_USERINFO, userInfo);
        return "ok";
    }
    @RequestMapping("/get")
    public UserInfo get(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        Object userObj = null;
        if (session != null && (userObj = session.getAttribute(SESSION_KEY_USERINFO)) != null) {
            return (UserInfo) userObj;
        }
        return null;
    }
}

通过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来修饰 

 

更多推荐

Leetcode.2591 将钱分给最多的儿童

题目链接Leetcode.2591将钱分给最多的儿童rating:1531题目描述给你一个整数moneymoneymoney,表示你总共有的钱数(单位为美元)和另一个整数childrenchildrenchildren,表示你要将钱分配给多少个儿童。你需要按照如下规则分配:所有的钱都必须被分配。每个儿童至少获得111美

第九天:QT入门保姆教程(常用的控件,信号与槽,定时器 QTimer,样式表 Qt Style Sheets,sqlite3数据库,开发板串口)

QT的简介我另外分享了一个qt案例源码包,里面包括文章中的任务源码和一系列常用案例需要的点击此处下载官网www.qt.ioQT是一个基于C++的跨平台的应用程序开发框架跨平台:一次编写,到处编译主流的平台都支持,如:Windows,Linux,Android,MacOS...应用程序:主要用于GUI程序开发,也可以用于

RT-Thread(学习)

RT-Thread是一款完全由国内团队开发维护的嵌入式实时操作系统(RTOS),具有完全的自主知识产权。经过16个年头的沉淀,伴随着物联网的兴起,它正演变成一个功能强大、组件丰富的物联网操作系统。RT-Thread概述RT-Thread,全称是RealTime-Thread,顾名思义,它是一个嵌入式实时多线程操作系统,

2023年最全详解:什么是销售管理?销售管理必备百科指南!

销售管理是什么?怎么样进行销售管理?都有哪些销售管理类型?销售管理都有哪些职责?如何高效的进行销售管理?本篇,我们将带大家深入浅出的了解销售管理,并且通过crm客户管理系统将销售管理的作用发挥到最大化!一、什么是销售管理?销售管理是现代企业不可或缺的重要部分。它涵盖了企业销售过程中的所有活动,包括市场营销、销售策略、销

企业商标信息API:品牌管理的秘密武器

引言当今数字时代,品牌管理变得比以往任何时候都更具挑战性。企业需要不断创新、保护知识产权、实时监测市场动态以及应对竞争压力。在这个竞争激烈的环境中,企业商标信息API已经成为品牌管理的秘密武器,为企业提供了无可估量的价值。企业商标信息API的作用企业商标信息API是一种应用程序接口,它允许企业访问商标数据库中的关键数据

生产制造业厂家固定资产怎么管理

固定资产的管理对于企业的运营效率和盈利能力具有重要影响。然而,传统的固定资产管理方法往往存在许多问题,如资产的低效使用、维护成本高昂以及决策者对资产价值缺乏准确了解等。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;因此,我们需要采用一种全新的方式来管理我们的固定资产。本

MySQL常见面试题(一)

😀前言在数据库管理系统中,存储引擎起着核心的角色,它决定了数据管理和存储的方式。MySQL作为一个领先的开源关系型数据库管理系统,提供了多种存储引擎来满足不同的需求和优化不同的应用。除了选择合适的存储引擎,数据库的设计还涉及到范式设计和表设计,这两者都对数据库的性能和数据一致性有深远的影响。在本文中,我们将探讨MyS

清易低功耗智能雨量监测站概述

一、低功耗智能雨量监测站概述产品概述低功耗智能雨量监测站基于智能传感、无线通信、智能处理与智能控制等物联网技术的开发,利用智能传感技术,通过传感器测量降雨量,并使用物联网进行传输。无需专门的通信线路,在联网的状态下,数据可快速、主动的上报到云平台,用户可在电脑或手机,随时随地浏览数据。二、技术参数测量参数降雨量◇测量范

Faunadb

Faunadb和googlespanner都属于云分布式数据库天然支持分片(无需做分表分库操作,一库搞定,当然价格另说),国内的也有比如TiDBOceanbase等本文使用java语言,其他语言可以跳过;有想直接使用的可以参考(无法访问外网,可以搞个vpn吧!!!,有时会遇到网络问题):GitHub-fauna/fau

WebGIS开发教程:Cesium里面的Entity和primitive有什么区别

EntityEntity是Cesium中最重要的概念之⼀,它通常用于描述具有坐标位置的实际对象,例如⻜机、汽⻋、楼房、⼈物等。每个Entity实例都有不同的属性,例如位置、姿态、缩放、颜⾊、贴图等,并且可以通过编程⽅式创建、修改、删除。Entity的优点是⾮常灵活和易于使用。由于Entity是更⾼层次的概念,因此它可以

Vue中如何进行跨域处理

Vue中的跨域请求处理:解决前端开发中的常见问题跨域请求是前端开发中常见的问题之一。Vue.js是一款流行的前端框架,如何在Vue中处理跨域请求是每个Vue开发者都需要了解的重要课题。本文将深入探讨什么是跨域请求,为什么它会出现,以及如何在Vue中处理跨域请求,包括使用代理、JSONP、CORS等方法。什么是跨域请求?

热文推荐