当前位置: 首页 > news >正文

Redis学习3 Redis的JAVA客户端

また会おう 呼んでくれるかい?

Redis的JAVA客户端

‌Jedis‌是一个用Java编写的高性能Redis客户端,专为简化Java应用与Redis数据库之间的交互而设计,被广泛用于各类Java项目中。

Jedis核心功能与特性如下:

直接映射Redis命令‌:

Jedis 提供了与Redis原生命令对应的API,例如set()get()lpush()等,开发者可以像在Redis-CLI中一样直接调用命令。

支持多种连接模式‌:

单机连接:通过new Jedis(host, port) 直接连接。
连接池:使用JedisPool管理连接,提升性能和资源利用率,适合生产环境。
集群支持:通过JedisCluster连接Redis Cluster,实现分布式数据存储。
哨兵模式:支持高可用架构下的自动故障转移。

支持所有Redis数据类型‌:包括StringListSetHashZSet以及高级数据结构如JSONVectorSets

Jedis使用的基本步骤:

①引入基本依赖
②创建Jedis对象并建立连接
③使用Jedis对象的方法,执行Jedis操作
④释放资源

引入Redis依赖

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.7.0</version>
</dependency>

Jedis入门案例

进行Redis基础测试

@SpringBootTest
public class TestJedisApplicationTests {private Jedis TestJedis;// 引入AOP注解,在执行前建立Redis连接@BeforeEachpublic void SetUpJedis() {TestJedis = new Jedis("192.168.100.128",6379);TestJedis.auth("1234");TestJedis.select(4);}// 执行测试方法@Testpublic void TestString() {String SetResult = TestJedis.set("name","雷伊");System.out.println("result = "+SetResult);String TestName = TestJedis.get("name");System.out.println("name = "+TestName);}// 在每一次执行结束后释放连接资源@AfterEachpublic void DownJedis() {if(TestJedis!=null) {TestJedis.close();}}
}

效果如下:
image
image

测试Hash结构

@Test
public void TestHash() {TestJedis.hset("user:1","name","无法无天");TestJedis.hset("user:1","age","13");Map<String,String> TestResult = TestJedis.hgetAll("user:1");System.out.println(TestResult);
}

效果如下:
image
image

Jedis连接池

Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此使用Jedis连接池代替Jedis的直连方式。
使用静态单例+工厂方法实现连接池:

// src/main/java/org/example/utils/JedisConnectionFactory.java
public class JedisConnectionFactory {private static final JedisPool jedisPool;static {JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();jedisPoolConfig.setMaxTotal(8);jedisPoolConfig.setMaxIdle(8);jedisPoolConfig.setMinIdle(0);jedisPoolConfig.setMaxWait(Duration.ofMillis(1000));jedisPool = new JedisPool(jedisPoolConfig, "192.168.100.128", 6379, 1000, "1234");}public static Jedis getJedis() {return jedisPool.getResource();}
}

其中:

static{...}部分为静态代码块,在类第一次被加载到 JVM 时,静态代码块会自动执行且仅执行一次。这保证了连接池的初始化是线程安全的(JVM 类加载机制保证了这一点),无需额外的同步锁。

setMaxTotal(8)方法设置了连接池中允许存在的最大活跃连接数。如果所有连接都被占用且达到此上限,新请求将等待或报错。

setMaxIdle(8)方法设置了连接池中允许保留的最大空闲连接数量。即使没有请求,池中也最多保持 8 个连接不关闭。

setMinIdle(0)方法设置了连接池中至少保持的空闲连接数量。设为 0 表示在极低负载时,连接池可以完全清空空闲连接以节省资源。

setMaxWait(Duration.ofMillis(1000))设置了最大等待时间‌。当连接池已满(达到MaxTotal)且无空闲连接时,新请求最多等待1秒。如果1秒内仍无法获取连接,将抛出JedisConnectionException。这防止了线程无限期阻塞。

测试方法如下:

@SpringBootTest
public class TestJedisApplicationTests {private Jedis TestJedis;@BeforeEachpublic void SetUpJedis() {TestJedis = JedisConnectionFactory.getJedis();TestJedis.select(4);}@Testpublic void TestHash() {TestJedis.hset("user:2","name","往生回环");TestJedis.hset("user:2","age","15");Map<String,String> TestResult = TestJedis.hgetAll("user:2");System.out.println(TestResult);}@AfterEachpublic void DownJedis() {if(TestJedis!=null) {TestJedis.close();}}}

测试效果如下:
image
image

SpringDataRedis

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis

提供了对不同Redis客户端的整合(LettuceJedis)
提供了RedisTemplate统一API来操作Redis
支持Redis的发布订阅模型
支持Redis哨兵和Redis集群
支持基于Lettuce的响应式编程
支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
支持基于Redis的jDKCollection实现

SpringDataRedis入门

SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中:
image

引入相关依赖

<!-- Redis依赖 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis-test</artifactId><scope>test</scope>
</dependency>
<!-- 连接池依赖 -->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId>
</dependency>

设置配置文件的连接池信息,具体和之前连接池设置类似:

spring:data:redis:host: 192.168.100.128port: 6379password: 1234lettuce:pool:max-active: 8max-idle: 8min-idle: 0max-wait: 100ms

编写测试方法:

@SpringBootTest
public class TestSpringDataRedisApplicationTests {@Autowiredprivate RedisTemplate redisTemplate;@Testpublic void TestString() {redisTemplate.opsForValue().set("NewName","盖亚");Object name = redisTemplate.opsForValue().get("NewName");System.out.println("NewName is : "+name);}}

测试效果如下:
image

RedisTemplate的Serializer

在Redis客户端查看我们之前插入的数据,发现效果如下:
image
image

出现这样的原因是RedisTemplate默认使用了JDK序列化机制‌

在SpringDataRedis中,RedisTemplate如果没有显式配置序列化器,其默认的KeyValue序列化器均为JdkSerializationRedisSerializer。该序列化器会将Java对象(包括 String)序列化为二进制字节流,以便在网络传输和存储时保持对象的完整结构。

我们所看到的\xAC\xED\x00\x05...Java对象序列化后的头部标识和二进制数据\xAC\xEDJava序列化流的魔术头(Magic Number),后续的字节包含了类描述信息、长度信息等。

因此,虽然存入的是字符串NewName盖亚,但在Redis中实际存储的是它们的二进制序列化形式,导致在Redis客户端(如CLI或GUI工具)中查看时显示为乱码或十六进制字符

这样的缺点就是:

可读性差
内存占用较大

通过配置GenericJacksonJsonRedisSerializer,将Java对象序列化为JSON格式存储,便于调试、监控以及与其他非Java系统交互。具体体现为实现配置类,自定义RedisTemplateBean

@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String,Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);ObjectMapper mapper = new ObjectMapper();GenericJacksonJsonRedisSerializer jsonRedisSerializer = new GenericJacksonJsonRedisSerializer(mapper);template.setKeySerializer(RedisSerializer.string());template.setHashKeySerializer(RedisSerializer.string());template.setValueSerializer(jsonRedisSerializer);template.setHashValueSerializer(jsonRedisSerializer);return template;}
}

其中:

new RedisTemplate<>()‌:创建一个新的Redis操作模板实例。泛型<String, Object>表示Key类型为String,Value,类型为任意Object

setConnectionFactory(...)‌:注入由Spring容器管理的RedisConnectionFactory(通常是Lettuce或Jedis的连接工厂)。这是建立与 Redis 服务器物理连接的基础。

ObjectMapper‌是Jackson库的核心类,负责JSON的序列化与反序列化。这里使用默认配置

GenericJacksonJsonRedisSerializer‌:是一个通用的JSON序列化器。它不仅能序列化具体的JAVA对象,还能在JSON中嵌入类型信息(通常是一个@class字段)。

RedisSerializer.string()用于获取一个StringRedisSerializer实例,从而确保Redis的Key‌和Hash结构的Field‌以纯字符串形式存储

重新测试,效果如下:
image

使用实体类测试:

@Test
public void TestPojo() {redisTemplate.opsForValue().set("PojoName",new User(1,"卡修斯",100,99));Object TestUser = redisTemplate.opsForValue().get("PojoName");System.out.println(TestUser);
}

效果如下:
image
image

StringRedisTemplate

执行如下测试方法时,

@Test
public void TestPojo() {redisTemplate.opsForValue().set("PojoName",new User(1,"卡修斯",100,99));User TestUser = (User)redisTemplate.opsForValue().get("PojoName");System.out.println(TestUser);
}

会报错

java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to classorg.example.pojo.User (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; 
org.example.pojo.User is in unnamed module of loader 'app')at org.example.TestSpringDataRedisApplicationTests.TestPojo(TestSpringDataRedisApplicationTests.java:32)

其根本原因是:‌GenericJacksonJsonRedisSerializer在反序列化时,如果没有找到类型信息(@class字段),或者配置不当,会将JSON对象默认反序列化为LinkedHashMap,而不是要求的User类。

解决方法为:使用StringRedisTemplate存储纯字符串类型的JSON,再使用objectMapper手动反序列化

@SpringBootTest
public class TestSpringDataRedisApplicationTests {@Autowiredprivate ObjectMapper objectMapper;@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testpublic void TestPojo() {User NewUser = new User(1,"卡修斯",100,99);String UserJson = objectMapper.writeValueAsString(NewUser);stringRedisTemplate.opsForValue().set("PojoName",UserJson);String TestUserJson = Objects.requireNonNull(stringRedisTemplate.opsForValue().get("PojoName"));User TestUser = objectMapper.readValue(TestUserJson,User.class);System.out.println(TestUser);}
}

image

RedisTemplate操作Hash结构

使用StringRedisTemplateopsForHash()方法完成Redis的Hash结构存储,测试方法如下:

@Test
public void TestHash() {stringRedisTemplate.opsForHash().put("User:404","name","木谷高明");stringRedisTemplate.opsForHash().put("User:404","age","18");stringRedisTemplate.opsForHash().put("User:404","company","Bushiroad");Map<Object,Object> HashEntry = stringRedisTemplate.opsForHash().entries("User:404");System.out.println(HashEntry);}

测试效果如下:
image
image

http://www.jsqmd.com/news/728146/

相关文章:

  • 解决方案:Umi-OCR批量处理性能提升40%的架构优化指南
  • C++笔记 forward完美转发
  • Dify 2026插件签名机制失效全记录,如何在3分钟内验证插件完整性并拦截恶意注入?
  • 必读!北京房山区别墅改造公司排名前五测评,这家企业级公司拔
  • 「WordPress电商必备教学」如何删除WordPress媒体库没有在使用的图片或视频
  • PaddleOCR训练避坑指南:解决numpy版本冲突、KMP_DUPLICATE_LIB_OK报错等常见问题
  • ElefanteAI框架:构建稳健可扩展AI应用后端的完整指南
  • 84561
  • ubuntu 22.04如何安装libmodbus
  • C++日志 1——日志系统的概念与分类
  • 如何在macOS上免费获得炉石传说智能助手:HSTracker终极指南
  • Modbus调试踩坑实录:从0x01到0x0B,手把手教你定位和修复这9个常见通信故障
  • Android 腾讯X5WebView如何禁止系统自带剪切板和自定义剪切板视图
  • 【团队绩效域】信息系统项目管理师论文范文
  • 灵活押金——矮萝卜给企业松绑的第一把钥匙
  • 避坑指南:处理CHI电化学数据时,你的Python脚本可能遇到的5个常见错误
  • 别再为蓝牙数据格式发愁了!UniApp连接BLE设备,手把手教你搞定ArrayBuffer与16进制转换
  • 紧急预警:未嵌入成本控制的偏见检测=无效合规!R语言实时资源监控统计管道(含GPU/FLOPs联动计量模块)
  • 从‘拍电影’到‘做游戏’:手把手教你用UE5关卡蓝图实现摄像机平滑切换与镜头混合
  • 长安链开源训练营结营仪式报名!颁发证书 | 技术分享 | 现场抽奖
  • YOLO Face:如何在复杂场景下实现工业级人脸检测系统
  • Acrobat Pro隐藏技能:写几行JavaScript,把PDF书签变成可打印的目录页
  • 2026届必备的六大降重复率神器解析与推荐
  • 别再折腾listings了!用minted包在LaTeX里给Python代码高亮,保姆级配置避坑指南
  • 使用Python快速接入Taotoken聚合大模型API的完整教程
  • 巧固架堆垛技术解析:四家实力企业如何赋能仓储高效升级
  • 【R语言教育实战权威指南】:20年教学专家亲授5大交互式课堂落地模板,错过再等十年?
  • brew@认识homebrew基本概念@国内源配置@加速配置@一键安装方案
  • 思源宋体终极指南:7款免费商用字体快速上手全攻略
  • 不止于采集:将STM32光敏传感器数据上传到串口助手和OLED屏(双显示实战)