Spring整合Redis

前言

在Spring项目中整合Redis,能显著提升数据缓存、分布式锁、会话管理等操作的效率。Jedis作为轻量级的Java Redis客户端,搭配Spring Data Redis模块,能够简化Redis的连接和数据操作,实现更高性能的读写与灵活的缓存管理。本文将简要介绍如何在Spring中集成Jedis,配置连接池、数据序列化等内容,并通过封装工具类来优化Redis的使用体验。

[!NOTE]

Spring版本:5.3.27

JDK版本:1.8

本文基于Jedis在Spring中整合Redis

一、redis客户端分类

1.1客户端对比

特性JedisLettuceRedisson
线程安全×
支持集群
支持哨兵
支持发布/订阅
支持管道
支持异步操作×
支持响应式编程×
API直观性√(API简单易用)×(API较复杂)×(API较复杂,丰富的功能)
社区支持
性能性能较低(同步阻塞)高性能(异步非阻塞)高性能(异步非阻塞)
资源消耗较高(频繁创建连接)较低(连接复用)较低(连接复用)
高级功能支持××√(支持分布式锁、布隆过滤器等)
易用性高(简单易用)中等(需要更多配置)高(封装良好,功能丰富)
学习曲线中等陡峭(功能丰富,学习成本高)
文档完善度
客户端实例创建简单较复杂(需要配置)较复杂(需要配置)
连接池支持需要外部支持(如Apache Commons Pool)内置连接池内置连接池
跨语言支持×××
商业支持有社区版本支持有社区版本支持有社区版本支持,有商业支持

1.2客户端简要说明

Jedis:传统的Redis客户端,基于同步阻塞模型,不支持异步操作,在高并发场景下性能受限。使用起来比较简单,API直观,适合轻量级应用和快速开发。

Lettuce:基于Netty实现的异步非阻塞客户端,支持异步、响应式编程,性能较高,尤其适用于高并发应用。需要一些额外的配置,相较于Jedis,学习曲线略陡。

Redisson:功能最为丰富,除了基本的Redis操作外,还封装了分布式锁、布隆过滤器等高级功能,适合大型、分布式应用。其API相对复杂,学习成本较高,但提供了较强的扩展性和便捷的高级特性支持。

二、依赖项

2.1依赖项说明

spring-data-redis:

  • 这是Spring Data Redis模块的核心依赖,提供了对Redis的支持,简化Redis操作。
  • 封装了对Redis的连接、数据访问以及常用操作的API(如RedisTemplateStringRedisTemplate),并且兼容多种Redis客户端,包括Jedis和Lettuce。
  • 通过它可以轻松实现与Redis的交互,并支持连接池管理、事务支持和缓存抽象等功能。

jedis:

  • Jedis是一个轻量级的Java Redis客户端,用于直接操作Redis。
  • spring-data-redis虽然提供了对Redis操作的抽象,但并不包含Redis客户端,因此需要Jedis作为Redis的具体实现。
  • Jedis提供了同步的、简单易用的API,使得与Redis交互更加便捷。
  • RedisConnectionFactory中可以配置Jedis作为连接池,为RedisTemplate提供连接。

jackson-databind:

  • Jackson是Java中的一种常用JSON处理工具库,jackson-databind依赖提供了将Java对象和JSON之间互相序列化和反序列化的功能。
  • 在Redis中通常需要将复杂数据结构序列化为JSON格式存储,Jackson能够帮助实现对象到JSON的转换,特别适用于RedisTemplateGenericJackson2JsonRedisSerializer
  • jackson-databind结合RedisTemplate使用,可以方便地将Java对象转换成JSON格式存储到Redis中,以及从Redis中取出JSON字符串时将其反序列化为Java对象。

2.2pom文件

<dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-redis</artifactId><version>2.6.10</version>
</dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.7.0</version>
</dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.13.4</version>
</dependency>

三、配置文件

  • host:redis服务地址
  • port:redis服务端口(默认6379)
  • password:密码(如果设置了)
  • timeout:处理客户端请求超时时间
  • pool.max-total:连接池最大连接数(包括空闲连接和正在使用的连接。当连接池中的连接数量达到 maxTotal 时,如果有新的请求想要连接,连接池将会等待,直到有连接被释放为止)
  • pool.max-idle:连接池最大空闲连接数(当连接池中空闲连接的数量超过 maxIdle 所设置的值时,连接池会尽量释放多余的连接。这样可以避免资源的浪费,确保系统的性能和稳定性。)
  • pool.min-idle:连接池最小空闲连接数
redis.host=*.*.*.*
redis.port=6379
redis.password=123456
redis.timeout=60000
redis.pool.max-total=8
redis.pool.max-idle=8
redis.pool.min-idle=0

3.1配置类

3.1.1配置类说明

  • 客户端及连接池配置属性使用@Value注入

  • 定义了两个Spring管理的bean,分别是redisConnectionFactoryredisTemplate

  • redisConnectionFactory用于创建和配置RedisConnectionFactory实例,以便为应用程序提供与Redis数据库的连接。

3.1.2redisConnectionFactory

Redis服务器地址配置:
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(host, port);
config.setPassword(password);
  • RedisStandaloneConfiguration用于指定Redis的主机地址(host)和端口(port)。确保应用程序可以正确地连接到指定的Redis服务器。
  • 如果Redis设置了密码保护,config.setPassword(password)配置会将连接密码添加到连接配置中,以实现安全连接。
Jedis连接池配置:
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(maxTotal);
poolConfig.setMaxIdle(maxIdle);
poolConfig.setMinIdle(minIdle);

用于设置连接池的参数,以优化Redis连接的性能:

  • setMaxTotal(maxTotal):设置最大连接数,以确保高并发访问时,系统能承受足够的连接。
  • setMaxIdle(maxIdle):设置连接池中的最大空闲连接数。闲置的连接可以快速被重用,减少重新创建连接的开销。
  • setMinIdle(minIdle):设置连接池中的最小空闲连接数,以便在连接池变空时保留一些空闲连接,保障连接的可用性。
Jedis客户端配置:
JedisClientConfiguration clientConfig = JedisClientConfiguration.builder().usePooling().poolConfig(poolConfig).and().readTimeout(java.time.Duration.ofMillis(timeout)).build();

配置了Jedis客户端的特定设置:

  • .usePooling()启用连接池,提升资源管理效率。
  • .poolConfig(poolConfig)将先前设置的poolConfig应用于Jedis的连接池。
  • .readTimeout(java.time.Duration.ofMillis(timeout))设置了Redis的读取超时时间,确保应用程序在与Redis通信时不会因等待过久而阻塞。
小结

创建一个配置完善的RedisConnectionFactory实例,它将连接信息、连接池、客户端参数等封装起来,便于整个应用与Redis交互时高效、安全地使用连接池,提高资源利用率,保障Redis服务的稳定性。

3.1.3redisTemplate

创建RedisTemplate实例并配置连接工厂:

RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
  • RedisTemplate<String, Object>:定义了键为String类型、值为Object类型的模板实例,可以灵活存储任意Java对象。
  • template.setConnectionFactory(redisConnectionFactory):将RedisConnectionFactory注入RedisTemplate,使其具备与Redis服务器通信的能力。通过该连接工厂,RedisTemplate可以根据配置好的连接池、连接地址和超时设置来访问Redis。
配置键的序列化方式:
template.setKeySerializer(new StringRedisSerializer());
  • setKeySerializer(new StringRedisSerializer()):将键的序列化方式设为StringRedisSerializer,确保键以字符串形式存储在Redis中。字符串序列化通常便于调试和维护,适合大多数场景。
配置值的序列化方式:
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
  • setValueSerializer(new GenericJackson2JsonRedisSerializer()):设置值的序列化方式为GenericJackson2JsonRedisSerializer,该序列化器将Java对象序列化为JSON格式。这样可以直观地将复杂对象序列化为JSON字符串,便于存储和读取。JSON格式也能在不同语言中通用,提高了数据的可读性和可移植性。
配置哈希类型键值对的序列化方式:
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
  • setHashKeySerializersetHashValueSerializer分别为哈希类型键和值指定序列化方式。Redis支持哈希结构(类似于字典),其中HashKey用于指定字段,HashValue用于指定字段的值。
  • StringRedisSerializer使得哈希键可以更易读地以字符串形式存储。
  • GenericJackson2JsonRedisSerializer使得哈希值也可以存储为JSON格式的字符串,适合复杂数据类型。
小结
  1. 便捷的Redis操作接口:封装了操作Redis常用方法,如opsForValue()(字符串操作)、opsForHash()(哈希操作)等,使得代码逻辑更加清晰。
  2. 序列化配置增强兼容性RedisTemplate支持灵活的序列化设置,使得Redis可以存储任意Java对象而不失去可读性。
  3. 集中管理Redis连接:通过注入的RedisConnectionFactoryRedisTemplate能够高效、可靠地管理连接池,提高Redis交互效率。

3.1.4完整配置类

package com.lazy.snail.config;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;/*** @ClassName RedisConfig* @Description TODO* @Author lazysnail* @Date 2024/11/11 15:07* @Version 1.0*/
@Configuration
public class RedisConfig {@Value("${redis.host}")private String host;@Value("${redis.port}")private int port;@Value("${redis.password}")private String password;@Value("${redis.timeout}")private int timeout;@Value("${redis.pool.max-total}")private int maxTotal;@Value("${redis.pool.max-idle}")private int maxIdle;@Value("${redis.pool.min-idle}")private int minIdle;@Beanpublic RedisConnectionFactory redisConnectionFactory() {// 配置Redis服务器地址RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(host, port);config.setPassword(password);// 配置Jedis连接池JedisPoolConfig poolConfig = new JedisPoolConfig();poolConfig.setMaxTotal(maxTotal);poolConfig.setMaxIdle(maxIdle);poolConfig.setMinIdle(minIdle);JedisClientConfiguration clientConfig = JedisClientConfiguration.builder().usePooling().poolConfig(poolConfig).and().readTimeout(java.time.Duration.ofMillis(timeout)).build();return new JedisConnectionFactory(config, clientConfig);}@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);// 设置key的序列化方式template.setKeySerializer(new StringRedisSerializer());// 设置value的序列化方式template.setValueSerializer(new GenericJackson2JsonRedisSerializer());template.setHashKeySerializer(new StringRedisSerializer());template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());return template;}
}

四、redis工具类

4.1工具类作用

  • 封装通用操作,简化调用RedisUtil将Redis的常用操作方法(如setgetdelete等)进行封装,简化了调用逻辑。无需直接操作RedisTemplate的API,而是通过工具类的方法进行更直观的操作。例如,set方法统一了过期时间的设置,get方法直接获取值,代码更加清晰易读。

  • 提升代码复用性:在项目中,操作Redis的代码可能会散布在各个业务模块中。通过RedisUtil工具类,将Redis操作集中管理,可以避免重复的代码,提升复用性,并且在需要更改Redis操作时,只需修改工具类即可,维护性更强。

  • 方便扩展和管理:通过工具类,可以轻松扩展更多的Redis操作方法,如设置集合、哈希、列表等数据结构的操作。如果需要增加更多的Redis配置(如不同的序列化方式),也可以通过工具类实现集中管理。

  • 增强代码可读性:直接调用RedisTemplate的API会显得代码复杂和难以理解。使用RedisUtil的封装方法后,操作描述更直观,有助于增强代码的可读性,更容易理解Redis的操作逻辑。

  • 便于统一异常处理和业务逻辑封装:工具类可以将一些异常捕获逻辑集中在一起进行处理。例如,如果Redis连接超时,可以在工具类中进行处理,避免各个模块中都添加重复的异常捕获代码,统一了异常处理的逻辑。

4.2工具类代码

package com.lazy.snail.util;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;import java.util.concurrent.TimeUnit;/*** @ClassName RedisUtil* @Description TODO* @Author lazysnail* @Date 2024/11/11 16:47* @Version 1.0*/
@Component
public class RedisUtil {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;public void set(String key, Object value, long timeout) {redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);}public Object get(String key) {return redisTemplate.opsForValue().get(key);}public boolean delete(String key) {return Boolean.TRUE.equals(redisTemplate.delete(key));}public boolean hasKey(String key) {return Boolean.TRUE.equals(redisTemplate.hasKey(key));}public boolean expire(String key, long timeout) {return Boolean.TRUE.equals(redisTemplate.expire(key, timeout, TimeUnit.SECONDS));}
}

五、测试类

5.1测试类代码

package com.lazy.snail;import com.lazy.snail.config.AppConfig;
import com.lazy.snail.util.RedisUtil;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = AppConfig.class)
@TestPropertySource("classpath:application.properties")
public class SpringTest {@Autowiredprivate RedisUtil redisUtil;@Testvoid test() {redisUtil.set("test", "test", 60);redisUtil.delete("test");}
}

5.2测试结果:

image-20241112135211896

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

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

相关文章

将已有的MySQL8.0单机架构变成主从复制架构

过程: 把数据库做一个完全备份, 恢复到从节点上, 恢复后从备份的那个点开始往后复制,从而保证后续数据的一致性。 步骤: 修改 master 主节点 的配置&#xff08; server-id log-bin &#xff09;master 主节点 完全备份&#xff08; mysqldump &#xff09;master 主节点 创建…

一文3000字从0到1带你进行Mock测试(建议收藏)

​什么是mock&#xff1f; ​mock测试是以可控的方式模拟真实的对象行为。程序员通常创造模拟对象来测试对象本身该具备的行为&#xff0c;很类似汽车设计者使用碰撞测试假人来模拟车辆碰撞中人的动态行为 为什么要使用Mock&#xff1f; 之所以使用mock测试&#xff0c;是因…

小程序如何完成订阅

小程序如何完成订阅 参考相关文档实践问题处理授权弹窗不再触发引导用户重新授权 参考相关文档 微信小程序实现订阅消息推送的实现步骤 发送订阅消息 小程序订阅消息&#xff08;用户通过弹窗订阅&#xff09;开发指南 实践 我们需要先选这一个模板&#xff0c;具体流程参考…

SOHO场景开局(小型,多子网):AP+管理型交换机+路由器+光猫

业务需求 1. 实现除光猫外&#xff0c;整网设备通过APP进行开局&#xff0c;开局部署完成后&#xff0c;能够通过APP远程运维。 2. 需要单独划分访客、办公、视频监控3个子网&#xff0c;其中访客子网供顾客无线上网使用&#xff0c;办公子网用于接入无线和有线办公终端&#x…

C++map和set(二)

1.map的opeator[] 功能&#xff1a; 如果访问对象存在就返回指定键的值的引用&#xff0c;如果指定的键不存在会插入新的键值对&#xff0c;键是传递给operator[]的参数&#xff0c;值是使用该值类型的默认构造函数构造的(对于简单类型通常是0或者空字符)。 代码示例&#xf…

[Linux]多线程详解

多线程 1.线程的概念和理解1.1线程的优点1.2线程的缺点1.3线程的设计1.4线程 VS 进程 2.线程控制2.1线程等待2.2 线程终止2.3 线程分离 3.线程互斥3.1背景3.2抢票代码演示3.3保护公共资源&#xff08;加锁&#xff09;3.3.1创建锁/销毁锁3.3.2申请锁/尝试申请锁/解锁 3.4解决抢…

大学语文教材电子版(第十一版)教学用书PDF及课件

大学语文课件&#xff1a;https://caiyun.139.com/m/i?005CiDusEVWnR 《大学语文》&#xff08;第十一版&#xff09;主编&#xff1a;徐中玉 齐森华 谭帆。 大学语文教材电子版教师用书PDF第一课《齐桓晋文之事》艺术赏析&#xff1a; 孟子四处游说&#xff0c;养成善辩的…

MySQL【七】

字符串函数 数学函数 日期函数 条件控制函数 类型转换函数 系统信息函数 自定义函数 DELIMITER  CREATE FUNCTION 函数名([参数名 参数数据类型[,…]])RETURNS 函数返回值的数据类型BEGIN函数体;RETURN 语句;ENDDELIMITER ;sql ########## 定义一个函数maxofthree()&#x…

第三百二十三节 Java线程教程 - Java同步器

Java线程教程 - Java同步器 同步器对象与一组线程一起使用。 它维护一个状态&#xff0c;根据它的状态&#xff0c;它让一个线程通过或强迫它等待。 本节将讨论四种类型的同步器&#xff1a; SemaphoresBarriersLatchesExchangers 信号量 信号量用于控制可以访问资源的线程…

《Java核心技术 卷I》用户界面AWT事件继承层次

AWT事件继承层次 EventObject类有一个子类AWTEvent&#xff0c;它是所有AWT事件类的父类。 Swing组件会生成更多其他事件对象&#xff0c;都直接拓展自EventObject而不是AWTEvent。 AWT将事件分为底层(low-level)事件和语义事件。 语义事件&#xff1a;表示用户的动作事件&…

Ubuntu从入门到精通(一)系统安装

Ubuntu从入门到精通&#xff08;一&#xff09; 1 Ubuntu镜像选择 下载Ubuntu 20.04系统ISO镜像 安装 Ubuntu 20.04系统,就必须有 Ubuntu 20.04系统软件安装程序可以通过浏览器访问Ubuntu20.04的官方站点&#xff0c; 然后在导舰栏找划 Dowwnloads->Mirrors链接&#xff…

用户自定义IP核——ZYNQ学习笔记6

一、试验任务 通过自定义一个 LED IP 核&#xff0c;通过 PS 端的程序来控制底板上 PL 端 LED1 呈现呼吸 灯的效果&#xff0c;并且 PS 可以通过 AXI 接口来控制呼吸灯的开关和呼吸的频率。 二、创建IP核 三、创建工程&#xff0c;调用IP #include "stdio.h" #includ…

Elasticsearch 8.16.0:革新大数据搜索的新利器

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

python:用 sklearn 构建 K-Means 聚类模型

pip install scikit-learn 或者 直接用 Anaconda3 sklearn 提供了 preprocessing 数据预处理模块、cluster 聚类模型、manifold.TSNE 数据降维模块。 编写 test_sklearn_3.py 如下 # -*- coding: utf-8 -*- """ 使用 sklearn 构建 K-Means 聚类模型 "&…

【大数据学习 | HBASE高级】hive操作hbase

一般在查询hbase的数据的时候我们可以直接使用hbase的命令行或者是api进行查询就行了&#xff0c;但是在日常的计算过程中我们一般都不是为了查询&#xff0c;都是在查询的基础上进行二次计算&#xff0c;所以使用hbase的命令是没有办法进行数据计算的&#xff0c;并且对于hbas…

贴代码框架PasteForm特性介绍之markdown和richtext

简介 PasteForm是贴代码推出的 “新一代CRUD” &#xff0c;基于ABPvNext&#xff0c;目的是通过对Dto的特性的标注&#xff0c;从而实现管理端的统一UI&#xff0c;借助于配套的PasteBuilder代码生成器&#xff0c;你可以快速的为自己的项目构建后台管理端&#xff01;目前管…

ServletConfig、ServletContext、HttpServletRequest与HttpServletResponse常见API

目录 一、ServletConfig 二、ServletContext 三、ServletContext其他重要API (一)获取文件路径和上下文 (二)域对象的相关API 四、HttpServletRequest常见API (一)获取请求行/头信息相关 (二)获得请求参数相关 五、HttpServletResponse常见API 一、ServletConfig Se…

MySQL缓存使用率超过80%的解决方法

MySQL缓存使用率超过80%的解决方法 一、识别缓存使用率过高的问题1.1 使用SHOW GLOBAL STATUS命令监控1.2 监控其他相关指标二、分析缓存使用率过高的原因2.1 数据量增长2.2 查询模式变化2.3 配置不当三、解决缓存使用率过高的方法3.1 调整Buffer Pool大小3.1.1 计算合理的Buff…

新手教学系列——善用 VSCode 工作区,让开发更高效

引言 作为一名开发者,你是否曾经在项目中频繁地切换不同文件夹,打开无数个 VSCode 窗口?特别是当你同时参与多个项目或者处理多个模块时,这种情况更是家常便饭。很快,你的任务栏上挤满了 VSCode 的小图标,切换起来手忙脚乱,工作效率直线下降。这时候,你可能会问:“有…

springboot004基于springboot004网页时装购物系统(源码+包运行+LW+技术指导)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…