在Redis官网中提供了各种语言的客户端,地址:https://redis.io/docs/latest/develop/clients/

其中Java客户端也包含很多:

Jedis和Lettuce:这两个主要是提供了Redis命令对应的API,方便我们操作Redis,而SpringDataRedis又对这两种做了抽象和封装,因此我们后期会直接以SpringDataRedis来学习。
Redisson:是在Redis基础上实现了分布式的可伸缩的java数据结构,例如Map、Queue等,而且支持跨进程的同步机制:Lock、Semaphore等待,比较适合用来实现特殊的功能需求。
1.Jedis客户端
Jedis的官网地址: https://github.com/redis/jedis
1.1. 快速入门
我们先来个快速入门:
1)引入依赖:
<!--jedis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
2)建立连接
新建一个单元测试类,内容如下:
BeforeEach
@BeforeEach 是 JUnit 5 测试框架中的一个注解,用于在每个测试方法执行之前运行一些初始化代码。
使用场景
初始化数据或状态。
重置某些对象的状态。
准备测试资源,比如数据库连接、文件等。
@BeforeEach 是一个非常有用的注解,可以让你专注于测试逻辑,而不用担心每次重复编写初始化代码,提高了测试代码的可维护性和清晰性。
private Jedis jedis;
@BeforeEach
void setUp() {
// 1.建立连接
// jedis = new Jedis("192.168.150.101", 6379);
使用连接池创建!!!!
jedis = JedisConnectionFactory.getJedis();
// 2.设置密码
jedis.auth("123321");
// 3.选择库
jedis.select(0);
}
3)测试:
@Test
void testString() {
// 存入数据
String result = jedis.set("name", "虎哥");
System.out.println("result = " + result);
// 获取数据
String name = jedis.get("name");
System.out.println("name = " + name);
}
@Test
void testHash() {
// 插入hash数据
jedis.hset("user:1", "name", "Jack");
jedis.hset("user:1", "age", "21");
// 获取
Map<String, String> map = jedis.hgetAll("user:1");
System.out.println(map);
}
AfterEach和BeforeEach功能类似
4)释放资源
@AfterEach
void tearDown() {
if (jedis != null) {
jedis.close();
}
}
1.2. 连接池
Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此我们推荐大家使用Jedis连接池代替Jedis的直连方式。
下面代码说明
定义了一个工具类—— JedisConnectionFactory
一个静态成员变量—— jedisPool
然后通过一个静态代码块(通常用于在类被加载时完成一些静态变量的初始化),对jedisPool初始化
提供一个静态方法,方便从连接池去获取Jedis对象——调用工具类的getJedis方法,从池子中去获取Jedis实例(对象),用完再还回去,避免频繁的创建和销毁
public class JedisConnectionFactory {
private static final JedisPool jedisPool;
static {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// 最大连接
jedisPoolConfig.setMaxTotal (8) ;
// 最大空闲连接
jedisPoolConfig.setMaxIdle(8);
// 最小空闲连接
jedisPoolConfig.setMinIdle(0);
// 設置最长等待时间,ms
jedisPoolConfig.setMaxWaitMillis (200);
jedisPool = new JedisPool(jedisPoolConfig, "192.168.150.101", 6379,1000, "123321") ;
}
// 获取Jedis对象
public static Jedis getJedis(){
return jedisPool. getResource();
}
}
package com.chinhae.jedis.util;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* 这个类是:
*
* @author: CHINHAE
* @date: 2025/10/11 13:07
* @version: 1.0
*/public class JedisConnectionFactory {
private static final JedisPool jedisPool;
static {
// 配置连接池
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxIdle(10);
poolConfig.setMaxTotal(10);
// 创建连接池对象
jedisPool = new JedisPool(poolConfig,"47.109.92.14",
6379,1000,"Qiu@CHINHAE!");
}
public static Jedis getJedis(){
return jedisPool.getResource();
}
}
package com.chinhae.test;
import com.chinhae.jedis.util.JedisConnectionFactory;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;
import java.util.Map;
/**
* 这个类是:
*
* @author: CHINHAE
* @date: 2025/10/11 12:52
* @version: 1.0
*/public class JedisTest {
private Jedis jedis;
@BeforeEach
void setUp() {
// 1.建立连接
//jedis = new Jedis("47.109.92.14", 6379);
jedis = JedisConnectionFactory.getJedis();
// 2.设置密码
jedis.auth("Qiu@CHINHAE!");
// 3.选择库
jedis.select(0);
}
@Test
void testString() {
// 存入数据
String result = jedis.set("test01", "胡歌");
System.out.println("result = " + result);
// 获取数据
String test01 = jedis.get("test01");
System.out.println("test01 = " + test01);
}
@Test
void testHash() {
jedis.hset("user:1", "name", "告诉");
jedis.hset("user:1","age","21");
// 获取
Map<String, String> map = jedis.hgetAll("user:1");
System.out.println("map = " + map);
}
@AfterEach
void tearDown() {
if (jedis != null) {
jedis.close();
}
}
}
2. Spring Data Redis
官网地址: https://spring.io/projects/spring-data-redis

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

SpringBoot已经提供了对SpringDataRedis的支持,使用非常简单:
1.引入依赖
<!--Redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--连接池依赖-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2.配置文件
spring:
data:
redis:
host: 47.109.92.14
port: 6379
password: Qiu@CHINHAE!
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
max-wait: 100ms
3.注入RedisTemplate,编写测试
package com.chinhae;
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
class SpringDataRedisDemoApplicationTests {
@Autowired
private RedisTemplate redisTemplate;
@Test
void testString() {
// 写入一条String数据
redisTemplate.opsForValue().set("name","虎哥");
// 获取string数据
Object name = redisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
}
}
会发现存入的数据是这样的乱码

就需要自定义RedisTemplate的序列化来显示了
2.2 SpringDataRedis的序列化方式
我们可以自定义RedisTemplate的序列化方式,代码如下:
package com.chinhae.redis.config;
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.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
/**
* 这个类是:
*
* @author: CHINHAE
* @date: 2025/10/11 15:01
* @version: 1.0
*/@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
// 创建RedisTemplate对象
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 设置连接工厂
template.setConnectionFactory(connectionFactory);
// 创建JSON序列化工具
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// 设置Key的序列化
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
// 设置Value的序列化
template.setValueSerializer(jsonRedisSerializer);
template.setHashValueSerializer(jsonRedisSerializer);
// 返回
return template;
}
}
测试:
package com.chinhae;
import com.chinhae.redis.entity.User;
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
class SpringDataRedisDemoApplicationTests {
@Autowired
private RedisTemplate<String,Object> redisTemplate;
@Test
void testString() {
// 写入一条String数据
redisTemplate.opsForValue().set("name","虎哥");
// 获取string数据
Object name = redisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
}
@Test
void testSaveUser() {
// 写入数据
redisTemplate.opsForValue().set("user:100",new User("虎哥",21));
// 获取数据
User o = (User)redisTemplate.opsForValue().get("user:100");
System.out.println("o = " + o);
}
}
package com.chinhae.redis.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 这个类是:
*
* @author: CHINHAE
* @date: 2025/10/11 15:13
* @version: 1.0
*/@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String name;
private Integer age;
}
2.3 StringRedisTemplate
尽管JSON的序列化方式可以满足我们的需求,但依然存在一些问题,如图:

为了在反序列化时知道对象的类型,JSON序列化器会将类的class类型写入json结果中,存入Redis,会带来额外的内存开销。
为了节省内存空间,我们并不会使用JSON序列化器来处理value,而是统一使用String序列化器,要求只能存储String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化。

Spring默认提供了一个StringRedisTemplate类,它的key和value的序列化方式默认就是String方式。省去了我们自定义RedisTemplate的过程:
package com.chinhae;
import com.chinhae.redis.entity.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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.StringRedisTemplate;
@SpringBootTest
class SpringDataRedisDemoStringTests {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
void testString() {
// 写入一条String数据
stringRedisTemplate.opsForValue().set("name","虎哥");
// 获取string数据
Object name = stringRedisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
}
private static final ObjectMapper mapper = new ObjectMapper();
@Test
void testSaveUser() throws JsonProcessingException {
// 创建对象
User user = new User("虎哥", 21);
// 手动序列化
String json = mapper.writeValueAsString(user);
// 写入数据
stringRedisTemplate.opsForValue().set("user:200",json);
// 获取数据
String jsonUser = stringRedisTemplate.opsForValue().get("user:200");
// 手动反序列化
User user1 = mapper.readValue(jsonUser, User.class);
System.out.println("user1 = " + user1);
}
}
RedisTemplate的两种序列化实践方案:
方案一:
- 自定义RedisTemplate
- 修改RedisTemplate的序列化器为GenericJackson2JsonRedisSerializer
方案二:
- 使用StringRedisTemplate
- 写入Redis时,手动把对象序列化为JSON
- 读取Redis时,手动把读取到的JSON反序列化为对象

