Springboot整合RedisTemplate以及业务工具类示例

news2024/11/24 15:51:38

docker安装Redis参考我另一篇博客Docker安装Redis及持久化

一、Get-Started

依赖

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!--Apache对象池技术,包括RedisConnecttionFactory等,引入这个依赖就不需要自己配置了-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

yml配置

springboot2.0.0过后默认使用lettuce.pool而不使用jedis.pool

spring:
  redis:
    host: 192.168.150.101
    password: 123321
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 1
        max-wait: 300

测试

package com.gzdemo.redisdemo;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
public class RedisTemplateTest {
    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    void testAdd() {
        // String
        redisTemplate.opsForValue().set("name","zhangsan");
        // set
        redisTemplate.opsForSet().add("myset","1");
        // zset
        redisTemplate.opsForZSet().add("myzset","stu1",10);
        //hash
        redisTemplate.opsForHash().put("myhash","stu1","1");
        //list
        redisTemplate.opsForList().leftPush("mylist","1");
    }
}

运行单元测试,发现redis保存的这5个键值对出现乱码,原因是RedisTemplate默认使用的是Jdk序列化器。
在这里插入图片描述
在这里插入图片描述

二、StringRedisTemplate

RedisTemplate常用方法:https://blog.csdn.net/zzvar/article/details/118388897

先运行单元测试把新增的5个数据删掉

    @Test
    void testRemove() {
        // String
        redisTemplate.delete("name");
        // set
        redisTemplate.opsForSet().remove("myset","1");
        // zset
        redisTemplate.opsForZSet().remove("myzset","stu1");
        //hash
        redisTemplate.opsForHash().delete("myhash","stu1");
        //list
        redisTemplate.opsForList().rightPop("mylist");
    }

将RedisTemplate换成StringRedisTemplate(使用了String序列化器)或者RedisTemplate<String,String>,不能是RedisTemplate<String,Object>,除非自己配置一个RedisTemplate<String,Object>

在这里插入图片描述

重新测试TestAdd
在这里插入图片描述

三、配置RedisTemplate<String,Object>(可选)

给RedisTemplate<String,Object>配置序列化器后,不会乱码。
可以直接用RedisTemplate<String,Object>传输一个对象(必须implements Serializable
但通常不用这种方式,而是直接把对象转成json字符串保存在redis中
Redis配置

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
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.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;

@Configuration
public class RedisConfig {

    /**
     * RedisTemplate配置
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        // 创建RedisTemplate<String, Object>对象
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();

        // 设置RedisTemplate的连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        // 自定义序列化器
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);//序列化的类型为Object
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); //序列化所有属性
        // om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); //设置这个过后,redis中的数据会携带该对象的类型,不方便读取
        jackson2JsonRedisSerializer.setObjectMapper(om);

        // key和hashKey的序列化器采用String
        redisTemplate.setKeySerializer(RedisSerializer.string());
        redisTemplate.setHashKeySerializer(RedisSerializer.string());

        // value和hashValue的序列化器采用jackson2JsonRedisSerializer
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        return redisTemplate;
    }
}

单元测试

    //使用RedisTemplate<String,Object>需要配置一个RedisTemplate<String,Object>
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Test
    public void Test1_Add(){
        User u = User.builder()
                .id(1000)
                .name("zhangsan")
                .phone("15730000001")
                .build();

        redisTemplate.opsForValue().set("user1", u);
    }

    @Test
    public void Test1_Get(){
        Object obj = redisTemplate.opsForValue().get("user1");
        // 这里不能把Object强转为User类 否则会java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.gzdemo.redisdemo.domain.User
        User user = JSONUtil.toBean(JSONUtil.toJsonStr(obj), User.class);
        System.out.println(user);
    }

四、StringRedisTemplate-以json字符串保存对象

通常用这种方式将某个对象保存在redis中,这种方式不需要类implements Serializable

	@Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Test
    public void Test2_Add(){
        User u = User.builder()
                .id(1000)
                .name("zhangsan")
                .phone("15730000001")
                .build();

        stringRedisTemplate.opsForValue().set("user2", JSONUtil.toJsonStr(u));
    }

    @Test
    public void Test2_Get(){
        String s = stringRedisTemplate.opsForValue().get("user2");
        User user = JSONUtil.toBean(s, User.class);
        System.out.println(user);
    }

五、实际开发

实际开发中,在使用到缓存的地方,定义一个业务工具类。这里举个例子,基于LearningRecord实体类,比如

import cn.hutool.json.JSONUtil;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.time.LocalDateTime;
...

@Component
@Slf4j
@RequiredArgsConstructor
public class LearningRecordCacheHandler {
    private final StringRedisTemplate redisTemplate;
    private final ILearningLessonService lessonService;
    private final LearningRecordMapper recordMapper;
    // 缓存前缀
    private static final String LEARNING_RECORD_CACHE_PREFIX="learning:record:";

    //1) 写入缓存
    public void writeRecordCache(LearningRecord record){
        log.info("缓存放入了消息:");
        // 1.转成只有三个属性的对象
        RecordCacheData cacheData = new RecordCacheData(record);
        // 2. 转成json 字符串
        String jsonData = JSONUtil.toJsonStr(cacheData);
        // 3 拼接key  learning:record:6688
        String key =LEARNING_RECORD_CACHE_PREFIX+record.getLessonId();
        // 4 存储缓存(覆盖)
        redisTemplate.opsForHash().put(key,record.getSectionId().toString(),jsonData);
        // 5 设置超时时间
        redisTemplate.expire(key, Duration.ofSeconds(60));

    }
    //2) 读取缓存
    public LearningRecord readRecordCache(Long lessonId,Long sectionId){
        //1 拼接key  learning:record:6688
        String key =LEARNING_RECORD_CACHE_PREFIX+lessonId;
        // 真正的是String
        Object o = redisTemplate.opsForHash().get(key, sectionId.toString());
        if(o==null){
            return null;
        }
        // {id:1,moment:30,finshsend:false}
        // 转成对象
        LearningRecord record = JSONUtil.toBean(o.toString(), LearningRecord.class);
        record.setLessonId(lessonId);
        record.setSectionId(sectionId);
        return record;
    }
    //3) 删除缓存
    public void removeRecordCache(Long lessonId,Long sectionId){
        //1 拼接key  learning:record:6688
        String key =LEARNING_RECORD_CACHE_PREFIX+lessonId;
        redisTemplate.opsForHash().delete(key,sectionId.toString());
    }
    // 存储缓存的对象
    @Data
    @NoArgsConstructor
    public class RecordCacheData{
        private Long id;
        private Boolean finished;
        private Integer moment;

        public RecordCacheData(LearningRecord record) {
            this.id = record.getId();
            this.finished = record.getFinished();
            this.moment = record.getMoment();
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C# 类型转换之显式和隐式

文章目录 1、显式类型转换2. 隐式类型转换3. 示例4. 类型转换的注意事项5. 类型转换的应用示例总结 在C#编程中&#xff0c;类型转换是一个核心概念&#xff0c;它允许我们在程序中处理不同类型的数据。类型转换可以分为两大类&#xff1a;显式类型转换&#xff08;Explicit Ca…

ctfshow-web入门-命令执行(web118详解)Linux 内置变量与Bash切片

输入数字和小写字母&#xff0c;回显 evil input 查看源码&#xff0c;发现这里会将提交的参数 code 传给 system 函数 使用 burpsuite 抓包进行单个字符的模糊测试 fuzz&#xff1a; 发现过滤掉了数字和小写字母以及一些符号&#xff0c;下面框起来的部分是可用的 结合题目提…

手把手教你:如何在51建模网免费下载3D模型?

作为国内领先的3D互动展示平台&#xff0c;51建模网不仅汇聚了庞大的3D模型资源库&#xff0c;供用户免费下载&#xff0c;更集成了在线编辑、格式转换、内嵌展示及互动体验等一站式功能&#xff0c;为3D创作者及爱好者搭建起梦想与现实的桥梁。 如何在51建模网免费下载3D模型…

恶意软件是什么意思?常见的恶意软件类型

您可能听说过很多有关恶意软件感染和运行服务器的危险的信息。但是&#xff0c;您可能还不清楚这在现实生活中意味着什么&#xff0c;或者该如何处理。让我们来了解一下&#xff1a;当人们谈论恶意软件时&#xff0c;他们真正指的是什么&#xff1f; 恶意软件是恶意软件的缩写&…

VehicleSPY的安装与使用

VehicleSPY介绍 Vehicle Spy 是美国英特佩斯公司的一款集成了诊断、节点/ECU仿真、数据获取、自动测试和车内通信网络监控等功能的工具&#xff0c;Vehicle Spy软件支持的应用场景很多&#xff0c;无法一一列举&#xff0c;以下是一些常见的应用&#xff1a; 总线监控&#x…

从百数教学看产品设计:掌握显隐规则,打造极致用户体验

字段显隐规则允许通过一个控件&#xff08;如复选框、单选按钮或下拉菜单&#xff09;来控制其他控件&#xff08;如文本框、日期选择器等&#xff09;和标签页&#xff08;如表单的不同部分&#xff09;的显示或隐藏。 这种规则通常基于用户的选择或满足特定条件来触发&#…

记一次阿里云服务器java应用无法响应且无法远程连接的问题排查

问题表现 java服务无响应&#xff0c;无法远程链接到服务器。 今天中午12点多&#xff0c;应用直接崩溃。后续进入到服务器&#xff0c;发现java进程都不在了&#xff0c; 排查过程 先安装atop工具 安装、配置并使用atop监控工具 等下次再出现时看相关时间点日志&#xff…

慢病精准预测:大模型 + 多模态融合

慢病精准预测&#xff1a;大模型 多模态融合 慢病预测算法拆解子解法1&#xff1a;多模态数据集成子解法2&#xff1a;实时数据处理与更新子解法3&#xff1a;采用大型语言多模态模型&#xff08;LLMMs&#xff09;进行深度学习分析 慢病预测更多模态 论文&#xff1a;https:/…

DC-DC 5V1A输出异步升压恒压芯片FP6291-5V/1A(5W)芯片,5V、9V、12V可调输出

FP6291LR-G1:DC-DC异步升压恒压5V/1A&#xff08;5W&#xff09;芯片&#xff0c;2.6-5.5V供电&#xff0c;内置MOS&#xff0c;最高输出5-12V/5-7W&#xff0c;输入限流可调 FP6291是一个电流模式升压DC-DC转换器。它的PWM电路内置0.2Ω功率MOSFET使该调节器高效。内部补偿网…

第4章 第一个程序

第4章 第一个程序 4.1 一个源程序从写出到执行的过程 第一步&#xff1a;编写汇编程序第二步&#xff1a;对源程序进行编译连接第三步&#xff1a;执行可执行文件中的程序 4.2.源程序 汇编语言中包含两种指令&#xff1a;汇编指令 和 伪指令 汇编指令&#xff1a;有对应机器…

挖逻辑漏洞不懂数据权限怎么赚大钱?

从开发的角度看权限漏洞的最后一篇了&#xff0c;也就是数据权限篇&#xff0c;虽然之前的都没什么人看&#xff0c;但想了想还是花时间写完了&#xff0c;也算有始有终吧。 0x00 相比于之前的未授权《一文理解权限类漏洞产生的原因之未授权篇》与功能权限《权限类漏洞解析—…

【实战场景】记一次UAT jvm故障排查经历

【实战场景】记一次UAT jvm故障排查经历 开篇词&#xff1a;干货篇&#xff1a;1.查看系统资源使用情况2.将十进制进程号转成十六进制3.使用jstack工具监视进程的垃圾回收情况4.输出指定线程的堆内存信息5.观察日志6.本地环境复现 总结篇&#xff1a;我是杰叔叔&#xff0c;一名…

20_系统测试与维护

目录 测试基础知识 测试原则 动态测试 静态测试 测试策略 测试阶段 测试用例设计 黑盒测试用例设计 白盒测试用例设计 McCabe度量法 鲁棒性测试 缺陷探测率(Defect Detection Percentage,DDP) 调试 系统维护基础 系统转换 系统维护指标 软件容错技术 嵌入式安…

Java语言开发的一套智慧产科系统源码:产科专科电子病历系统源码

Java语言开发的一套智慧产科系统源码&#xff1a;产科专科电子病历系统源码 系统概述 电子病历系统是以住院病人为中心&#xff0c;面向医生以及护士为主的&#xff0c;涉及临床治疗、护理等业务的临床信息系统&#xff0c;以电子信息技术为手段&#xff0c;实时采集病人在整个…

设计模式-结构型-08-组合模式

文章目录 1、学校院系展示需求2、组合模式基本介绍3、组合模式示例3.1、 解决学校院系展示&#xff08;透明模式1&#xff09;3.2、高考的科目&#xff08;透明模式2&#xff09;3.3、高考的科目&#xff08;安全组合模式&#xff09; 4、JDK 源码分析5、注意事项和细节 1、学校…

33.哀家要长脑子了!

憋说了&#xff0c;感觉好不容易长出来的脑子又缩回去了。。。 1.539. 最小时间差 - 力扣&#xff08;LeetCode&#xff09; 把所有时间排好序&#xff0c;然后计算两两之间的分钟差就好&#xff0c;但是要注意加上最后一个和第一个的判断&#xff0c;因为这个时间是按字典序来…

python-切片、集合

序列是指&#xff1a;内容连续、有序&#xff0c;可使用下标索引的一类数据容器 序列的常用操作 - 切片 切片的语法 序列的常用操作 - 切片 注意切片的范围是左闭右开 为什么使用集合 集合的常用操作 - 修改 集合的常用操作 - 集合长度 集合常用功能总结 集合的特点

为RK3568或RK3288开发板创建交叉编译环境{采用amd64的ubuntu系统配置交叉编译arm64开发环境}(保姆级包括安装QT)超详细记录版

为RK3568或RK3288开发板创建交叉编译环境{采用amd64的ubuntu系统配置交叉编译arm64开发环境}【保姆级包括安装QT】超详细记录版 Chapter1 为RK3568或RK3288开发板创建交叉编译环境{采用amd64的ubuntu系统配置交叉编译arm64开发环境}(保姆级包括安装QT)超详细记录版一. 安装QT程…

严防数据泄露:风险评估来预警,自查自纠防患未然!

近年来&#xff0c;随着数字化和网络化的快速发展&#xff0c;数据泄露事件呈现高发态势。网络攻击者利用复杂的攻击手段和技术&#xff0c;不断寻找和利用系统中的漏洞&#xff0c;以窃取或破坏数据&#xff0c;对企业声誉、客户信任以及经济利益造成巨大影响。 一、数据泄露的…

提升船舶轨迹查询效率

文章目录 引言I 优化思路1.1 表结构设计1.2 解析请求参数,定位到对应的表格进行查询1.3 mybatis查询1.4 效果II 工具方法2.1 日期处理2.2 spring开启debug日志引言 需求: 查询船舶轨迹 I 优化思路 1.1 表结构设计 按天存储轨迹数据,本文是一个月存储在6在表中,即:01,06…