Redis应用(8)——Redis的项目应用:结合SpringBoot如何在Redis里面存对象 RedisUtil工具类的封装 遇到的问题

在这里插入图片描述

前言

Redis作为一款优秀的开源、高效的内存数据库,在各种项目中都能见到其身影,熟练使用Redis是程序员必备的技能之一。本系列博客结合应用场景,阐述Redis从安装到使用的,从入门到进阶的相关内容。

本篇博客介绍在Spring项目中,如何往Redis里面存Java对象,以及使用中遇到的问题。

其他相关的Redis的博客如下:

Redis是啥 & 安装Docker的Redis & Redis的基本数据类型+常用命令 & SpringBoot整合Redis初步

在这里插入图片描述
结合redis.conf配置文件深入理解 Redis两种数据持久化方案:RDB和AOF

在这里插入图片描述

Redis数据的持久化 & CAP分布式理论(高可用性) & Redis主从搭建 & Redis的哨兵机制

在这里插入图片描述

在Linux上基于Docker容器Redis搭建一主二从三哨兵 & SpringBoot整合Redis哨兵

在这里插入图片描述

认识redis未授权访问漏洞 & 漏洞的部分复现 & 设置连接密码 & redis其他命令学习

在这里插入图片描述

Redis的项目应用(一):验证码 —> UUID到雪花ID & JMeter高并发测试 & 下载安装使用

在这里插入图片描述

Redis的项目应用(二):抢购图书 —> Redis高并发的问题 & 分布式锁Redission的使用

在这里插入图片描述
Redis的项目应用(三):抢购图书2.0 —> Lua脚本 & Redis+Lua+Redission实现抢购 & Redission锁

在这里插入图片描述

Redis的项目应用(四):缓存预热,用户注册为例 —>注册的流程 & 缓存预热的方式,quartz方式 / @Schedule方式

在这里插入图片描述
Redis的项目应用(五):缓存自动更新 —>Canal管道 & MySQL配置+安装canal & 入门案例 & Canal的项目应用

在这里插入图片描述
Redis的项目应用(六):布隆过滤器—白名单 ----> Reids的问题,雪崩/ 击穿 / 穿透【重要】& 布隆过滤器

在这里插入图片描述

Redis数据一致性 & 用Java代码加锁解决一致性 & 采用lua脚本实现减1的原子性 & 分布式环境下的setnex锁及其问题 & Redission框架的使用

在这里插入图片描述

IDEA启动两个Tomcat服务的方式 & 使用nginx进行反向代理 & JMeter测试分布式情况下synchronized锁失效

在这里插入图片描述

目录

  • 前言
  • 引出
  • 如何在redis里面存java对象
    • 1.本文的项目依赖
    • 2.核心配置类
    • 3.封装RedisUtil工具类
    • 4.工具类的使用
  • 在实际应用中遇到的bug
    • 1.问题描述
    • 2.问题解决
  • 总结

引出


1.之前的Redis相关博客的汇总;
2.redis里面存java对象的解决方案;
3.在实际使用中遇到的问题及处理;

如何在redis里面存java对象

1.本文的项目依赖

使用的是最基础的springboot的redis依赖

由于代码中用了布隆过滤器,因此这里引用了hutool工具包

        <!--        redis的依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!--        hutool工具包--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.11</version></dependency>

2.核心配置类

核心是存对象的Redistemplate配置,

还包括了Redisson的配置,lua脚本的配置。

package com.tianju.fresh.config;import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.springframework.context.annotation.Bean;
import org.redisson.config.Config;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;/*** Redisson的配置,lua脚本的配置,redis序列化存对象的配置*/
@Configuration
public class RedisConfig {/*** Redisson的配置,* Redisson框架,分布式环境下redis数据一致性* @return*/@Beanpublic RedissonClient redissonClient(){Config config = new Config();config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("5672");return Redisson.create(config);}/*** lua脚本的配置类,让减库存-1操作原子化* @return*/@Beanpublic RedisScript<Long> redisScript(){DefaultRedisScript redisScript = new DefaultRedisScript<>();redisScript.setResultType(Long.class);// lua脚本的位置redisScript.setLocation(new ClassPathResource("/lua/goods-unstock.lua") // 关联lua脚本);return redisScript;}/*** redis序列化的相关配置,可以存对象* @return*/@Beanpublic RedisTemplate redisTemplateInit(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(redisConnectionFactory);//设置序列化Key的实例化对象redisTemplate.setKeySerializer(new StringRedisSerializer());//设置序列化Value的实例化对象redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());/**** 设置Hash类型存储时,对象序列化报错解决*/redisTemplate.setHashKeySerializer(new StringRedisSerializer());redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());return redisTemplate;}}

3.封装RedisUtil工具类

在实际应用redis中形成的自定义的Redis工具类,主要把Redistemplate 和 StringRedistemplate 依赖注入,然后调用这两个的方法;

其中Redistemplate 用来存java对象,而StringRedistemplate 用于普通的操作;

package com.tianju.fresh.util;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;import java.util.Set;
import java.util.concurrent.TimeUnit;@Component
public class RedisUtil {@Autowiredprivate RedisTemplate<String,Object> redisTemplate;@Autowiredprivate StringRedisTemplate stringRedisTemplate;public void  saveObjectToRedis(String key,Object json){redisTemplate.opsForValue().set(key,json);}/*** 从redis里面获取json对象,如果没有,返回null* @param key* @return*/public Object getJsonFromRedis(String key){return redisTemplate.opsForValue().get(key);}/*** 删除redis里面的值,键* @param key 删除的键* @return*/public Boolean deleteKey(String key){return redisTemplate.delete(key);}/*** 存到Redis里面的 set 中* @param key 存的键* @param value 存到set的值*/public void saveSetToRedis(String key,String... value){for (String s:value){if (s!=null && !s.equals("")){stringRedisTemplate.opsForSet().add(key, s);}}}/*** 判断是否在redis的set中* @param key* @param val* @return*/public Boolean isInSet(String key,String val){return stringRedisTemplate.opsForSet().isMember(key, val);}/*** 获得set中的值* @param key 键* @return*/public Set<String> getSet(String key){return stringRedisTemplate.opsForSet().members(key);}/*** 从redis里面的set删除数据* @param key* @param val*/public void removeFromSet(String key,String val){stringRedisTemplate.opsForSet().remove(key, val);}/*** 获得存到redis里面的键对应的string类型的值* @param key 键* @return*/public String getStringValue(String key){return stringRedisTemplate.opsForValue().get(key);}/*** 保存到redis里面string* @param key* @param timeout 过期时间,传的是多少s之后过期* @param val*/public void saveStringValue(String key,String val,Integer... timeout){if (timeout==null){stringRedisTemplate.opsForValue().set(key,val);}else {stringRedisTemplate.opsForValue().set(key,val,timeout[0], TimeUnit.SECONDS);}}/*** 看某个键是否存在于Redis中* @param key 待检验的键* @return*/public Boolean isKeyInRedis(String key){return stringRedisTemplate.hasKey(key);}}

4.工具类的使用

下面以一个缓存预热的代码为例,使用工具类时依赖注入,然后调用工具类里面的方法

package com.tianju.fresh.autho.bloomFilter;import com.tianju.fresh.entity.Customer;
import com.tianju.fresh.mapper.CustomerMapper;
import com.tianju.fresh.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import java.util.HashSet;
import java.util.List;
import java.util.Set;/*** 将用户名,手机号码,邮箱存到redis里面,* 作用:* 1.登陆的时候先到redis里面查询;* 2.用户注册的时候先从redis里面看用户名是否重复*/
@Component
@Slf4j
public class LoginKeyPreHot {private final String LOGIN_KEY = "loginKey";@Autowiredprivate CustomerMapper customerMapper;@Autowiredprivate RedisUtil redisUtil;/*** 每天半夜 2点 跟新布隆过滤器和缓存*/@Scheduled(cron = "0 0 2 * * ?")public void perHot(){// 1.先清除缓存中的数据// 2.然后更新一下redis里面的loginKey;// 3.同时把loginKey放到布隆过滤器中redisUtil.deleteKey(LOGIN_KEY); // 删除redis里面的keySet set = new HashSet();List<Customer> customers = customerMapper.selectList(null);customers.forEach(c->{// 更新Redis里面的setredisUtil.saveSetToRedis(LOGIN_KEY, c.getUsername(),c.getEmail(),c.getContactTel());// 更新布隆过滤器BloomFilterUtil.addBloom(c.getUsername(),c.getEmail(),c.getContactTel());// 记录一下谁进了布隆过滤器中set.add(c.getUsername());set.add(c.getContactTel());set.add(c.getEmail());});// TODO:手动在布隆过滤器中放一个Arya, 模拟骗过了布隆过滤器,但没有骗过redis的情况BloomFilterUtil.addBloom("Arya");log.debug("缓存预热 + 布隆过滤器初始化成功 >>>" +set);}
}

在实际应用中遇到的bug

1.问题描述

如果在存redis的时候,用的是实现存java对象的序列化的Redistemplate,则此时就无法用SREM命令删除。

在这里插入图片描述

2.问题解决

要用stringRedisTemplate存就可以了

在这里插入图片描述


总结

1.之前的Redis相关博客的汇总;
2.redis里面存java对象的解决方案;
3.在实际使用中遇到的问题及处理;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/115221.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为云云耀云服务器L实例评测|2核2G跑mysql性能测试

前言 上一次我们介绍了华为云云耀云服务器L实例的基本信息&#xff0c;从购买到特色都做了简要介绍。但是 很多人看到这个配置又产生了迟疑&#xff0c;主要是因为云耀现在提供的全系是2核&#xff0c;性能吃得消吗&#xff1f;今天我们就来做一个性能测试 环境准备 因为我们…

2023-9-22 没有上司的舞会

题目链接&#xff1a;没有上司的舞会 #include <cstring> #include <iostream> #include <algorithm>using namespace std;const int N 6010;int n; int happy[N]; int h[N], e[N], ne[N], idx; bool has_father[N];// 两个状态&#xff0c;选该节点或不选该…

如何学好CTF

如何学好CTF CTF&#xff08;Capture The Flag&#xff09;是一种网络安全竞赛&#xff0c;需要参赛者解决各种加密、漏洞利用和数字取证等挑战。想要学好CTF&#xff0c;以下是一些建议&#xff1a; 1.学习基础知识&#xff1a;CTF竞赛需要掌握的基础知识包括操作系统、网络…

数据可视化 -- ECharts 入门

文章目录 引言1. ECharts的基本使用1.1 ECharts的快速上手1.2 相关配置讲解 2. ECharts常用图表2.1 图表1 柱状图2.1.1 柱状图的实现步骤2.1.2 柱状图的常见效果2.1.3 柱状图特点2.1.4 通用配置 2.2 图表2 折线图2.2.1 折线图的实现步骤2.2.2 折线图的常见效果2.2.3 折线图的特…

指标收集与分析:打造可观测性平台的关键技术【文末送书】

文章目录 写在前面兼容全域信号量所谓全域信号量有哪些&#xff1f;统一采集和上传工具统一的存储后台自由探索和综合使用数据好书推荐 写作末尾 写在前面 随着可观测性理念的深入人心&#xff0c;可观测性平台已经开始进入了落地阶段&#xff0c;它的先进性已经毋庸置疑&…

【100天精通Python】Day67:Python可视化_Matplotlib 绘动画,2D、3D 动画 示例+代码

1 绘制2D动画&#xff08;animation&#xff09; Matplotlib是一个Python绘图库&#xff0c;它提供了丰富的绘图功能&#xff0c;包括绘制动画。要绘制动画&#xff0c;Matplotlib提供了FuncAnimation类&#xff0c;允许您创建基于函数的动画。下面是一个详细的Matplotlib动画示…

尝试访问启动磁盘设置时出错怎么办?

当出现“尝试访问启动磁盘设置时出错”这样的错误提示&#xff0c;而且启动转换控制面板打不开了时&#xff0c;是无法开启触摸板功能的。我们可以使用以下方法来解决问题。 1. 在Windows桌面左下角搜索框输入“计算机管理”后点击“打开”。 2. 点击“本地用户与组”&#xff…

[JAVEee]SpringBoot项目的创建

SpringBoot可以更好的开发Spring项目,本文章将使用idea社区版来演示创建项目的过程与注意事项. SpringBoot的优点 SpringBoot中内置快速添加依赖的功能,能够便捷的集成各种框架,帮助开发.内置运行容器,无需配置Tomcat容器等其他web容器,可直接进行项目的部署与运行.更好的使用…

机器学习(15)---代价函数、损失函数和目标函数详解

文章目录 一、各自定义二、各自详解三、代价函数和损失函数区别四、例题理解 一、各自定义 1. 代价函数&#xff1a;代价函数&#xff08;Cost Function&#xff09;是定义在整个训练集上的&#xff0c;是所有样本误差的平均&#xff0c;也就是损失函数的平均。它用于衡量模型在…

有什么推荐使用的企业上网行为管理软件?

在当今信息化社会&#xff0c;企业的上网行为管理越来越重要。企业上网行为软件是一种能够监控和管理企业员工上网行为的工具&#xff0c;它可以帮助企业更好地管理网络资源&#xff0c;提高工作效率&#xff0c;保护企业信息安全&#xff0c;并符合相关的法律法规。本文将深入…

《信息系统项目管理师教程(第4版)》第1章至第5章 信息化发展、信息技术发展、信息系统治理、信息系统管理、信息系统工程 常见考点、知识点、思维导图、xmind

第一章至第五章多以选择题形式考察&#xff0c;分值在20分左右。已将考点、知识点整理成思维导图&#xff0c;可免费下载。以下是思维导图的部分截图&#xff1a; 第一章 信息化发展 第二章 信息技术发展 第三章 信息系统治理 第四章 信息系统管理 第五章 信息系统工程

【力扣】三角形最小路径和

目录 题目 例子 示例 1&#xff1a; 示例 2&#xff1a; 前言 思路 思想 代码 调用的函数 主函数 所有代码 力扣提交的代码 运行结果 小结 题目 给定一个三角形 triangle &#xff0c;找出自顶向下的最小路径和。 每一步只能移动到下一行中相邻的结点上。相邻的结…