目录
[1.1. 介绍](#1.1. 介绍)
[1.2. Jedis工程案例](#1.2. Jedis工程案例)
[1.2.1. 创建Maven工程](#1.2.1. 创建Maven工程)
[1.2.2. 创建Jedis对象建立连接](#1.2.2. 创建Jedis对象建立连接)
[1.2.3. 使用Jedis](#1.2.3. 使用Jedis)
[1.2.4. 释放资源](#1.2.4. 释放资源)
[1.2.5. 完整代码](#1.2.5. 完整代码)
[1.3. Jedis连接池](#1.3. Jedis连接池)
[2.1. 介绍](#2.1. 介绍)
[2.2. SpringDataRedis工程案例](#2.2. SpringDataRedis工程案例)
[2.2.1. 创建SpringBoot工程](#2.2.1. 创建SpringBoot工程)
[2.2.2. 引入依赖](#2.2.2. 引入依赖)
[2.2.3. 在application.yml配置Redis信息](#2.2.3. 在application.yml配置Redis信息)
[2.2.4. 注入RedisTemplate](#2.2.4. 注入RedisTemplate)
[2.3. 从lettuce改为Jedis](#2.3. 从lettuce改为Jedis)
[2.3.1. 移除当前lettuce依赖](#2.3.1. 移除当前lettuce依赖)
[2.3.2. 添加Jedis依赖](#2.3.2. 添加Jedis依赖)
[2.3.3. 修改配置文件指定使用Jedis](#2.3.3. 修改配置文件指定使用Jedis)
[2.4. RedisTemplate序列化/反序列化](#2.4. RedisTemplate序列化/反序列化)
[2.4.1. 自定义RedisTemplate](#2.4.1. 自定义RedisTemplate)
[2.4.2. 使用StringRedisTemplate](#2.4.2. 使用StringRedisTemplate)
一、Jedis入门
1.1. 介绍
**Jedis是Redis官方推荐的Java客户端开发工具。** Jedis提供了丰富的API,使得Java开发者可以方便地操作Redis数据库。Jedis支持Redis的所有数据结构操作,包括字符串、哈希、列表、集合和有序集合等类型的数据。
Jedis的设计考虑了连接池的管理,以优化性能和资源利用。由于直接创建和销毁连接资源非常消耗性能,Jedis提供了Jedis连接池技术,通过连接池管理Redis连接,避免了频繁创建和销毁连接的开销。使用连接池可以有效地提升Redis的性能和资源利用率。
在使用Jedis时,开发者需要注意线程安全问题。Jedis本身不是线程安全的,但在多线程环境下可以通过JedisPool管理多个独立的Jedis实例,每个线程使用自己的Jedis实例,从而保证线程安全。此外,Jedis的使用相对灵活,但也因此增加了编码的复杂度。
1.2. Jedis工程案例
1.2.1. 创建Maven工程
引入Jedis的Maven依赖
java
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>
1.2.2. 创建Jedis对象建立连接
java
jedis = new Jedis("49.233.186.253", 6379);
jedis.auth("wangzhexiao");
jedis.select(0);
1.2.3. 使用Jedis
方法名与Redis命令一致
java
String result = jedis.set("name", "王哲晓");
System.out.println("result = " + result);
String name = jedis.get("name");
System.out.println("name = " + name);
jedis.hset("people", "name", "王哲晓");
jedis.hset("people", "age", "34");
Map<String, String> people = new HashMap<>();
people.put("weight", "132");
people.put("height", "177");
jedis.hmset("people", people);
Map<String, String> result = jedis.hgetAll("people");
for (String key : result.keySet()) {
System.out.println("Key = " + key + ", Value = " + result.get(key));
}
String name = jedis.get("name");
System.out.println("name = " + name);
1.2.4. 释放资源
java
if (jedis != null) {
jedis.close();
}
1.2.5. 完整代码
XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>jedis-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<!-- Jedis依赖 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>
<!-- JUnit依赖 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.7.0</version>
</dependency>
</dependencies>
</project>
java
package com.example;
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.HashMap;
import java.util.List;
import java.util.Map;
public class JedisTest {
private Jedis jedis;
@BeforeEach // 用于在测试方法前执行操作,被执行操作的方法不能是静态的
void setUp() {
// 建立连接
jedis = new Jedis("49.233.186.253", 6379);
// 密码
jedis.auth("wangzhexiao");
// 选择数据库
jedis.select(0);
}
@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() {
jedis.hset("people", "name", "王哲晓");
jedis.hset("people", "age", "34");
Map<String, String> people = new HashMap<>();
people.put("weight", "132");
people.put("height", "177");
jedis.hmset("people", people);
Map<String, String> result = jedis.hgetAll("people");
for (String key : result.keySet()) {
System.out.println("Key = " + key + ", Value = " + result.get(key));
}
String name = jedis.get("name");
System.out.println("name = " + name);
}
@AfterEach // 用于在测试方法后执行操作,被执行操作的方法不能是静态的
void tearDown() {
if (jedis != null) {
jedis.close();
}
}
}
1.3. Jedis连接池
Jedis本身是线程不安全的,并且频繁地创建和销毁连接会有性能损耗,因此我们推荐大家使用Jedis连接池代替Jedis直连方式。
java
package com.example;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisConnectionFactory {
private static final JedisPool jedisPool;
static {
JedisPoolConfig config = new JedisPoolConfig();
// 最大连接数
config.setMaxTotal(10);
// 最大空闲连接
config.setMaxIdle(8);
// 最小空闲连接
config.setMinIdle(0);
// 设置最长等待时间ms
config.setMaxWaitMillis(200);
// 配置、连接地址、端口、超时时间、密码
jedisPool = new JedisPool(config, "49.233.186.253", 6379, 1000, "wangzhexiao");
}
public static Jedis getJedis() {
return jedisPool.getResource();
}
}
二、SpringDataRedis
2.1. 介绍
SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis,官网地址:
https://spring.io/projects/spring-data-redis
- 提供了对不同Redis客户端的整合(Lettuce和Jedis)
- 提供了RedisTemplate统一API来操作Redis
- 支持Redis的发布订阅模型
- 支持Redis哨兵和Redis集群
- 支持基于Lettuce的响应式编程
- 支持基于JDK、JSON、字符串、Spring对象的数据序列化即反序列化
- 支持基于Redis的JDKCollection实现
SpringDataRedis提供了RedisTemplate工具类,其中封装了各种对Redis的操作,并且将不同数据类型的操作API封装到了不同的类型中:
|-----------------------------|-----------------|-----------------|
| API | 返回值类型 | 说明 |
| redisTemplate.opsForValue() | ValueOperations | 操作String类型数据 |
| redisTemplate.opsForHash() | HashOperations | 操作Hash类型数据 |
| redisTemplate.opsForList() | ListOperations | 操作List类型数据 |
| redisTemplate.opsForSet() | SetOperations | 操作Set类型数据 |
| redisTemplate.opsForZSet() | ZSetOperations | 操作SortedSet类型数据 |
| redisTemplate | | 通用的命令 |
2.2. SpringDataRedis工程案例
2.2.1. 创建SpringBoot工程
2.2.2. 引入依赖
XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>SpringDataRedisDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringDataRedisDemo</name>
<description>SpringDataRedisDemo</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.2.3. 在application.yml配置Redis信息
XML
spring:
application:
name: spring-data-redis
data:
redis:
password: wangzhexiao
host: 49.233.186.253
port: 6379
lettuce:
pool:
max-active: 10 # 最大连接
max-idle: 10 # 最大空闲连接
min-idle: 0 # 最小空闲连接
max-wait: 100 # 连接等待时间
2.2.4. 注入RedisTemplate
java
package com.example.springdataredisdemo;
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 contextLoads() {
redisTemplate.opsForValue().set("name", "王哲晓");
String name = (String) redisTemplate.opsForValue().get("name");
System.out.println(name);
}
}
2.3. 从lettuce改为Jedis
从SpringBoot2.X 版本后,默认使用的redis客户端是Lettuce,如果你想从lettuce客户端更换为Jedis客户端,你需要做以下几步:
2.3.1. 移除当前lettuce依赖
如果pom.xml中有以下依赖的话,移除掉:
XML
<dependency>
<groupId>io.lettuce.core</groupId>
<artifactId>lettuce-core</artifactId>
</dependency>
2.3.2. 添加Jedis依赖
XML
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
2.3.3. 修改配置文件指定使用Jedis
XML
spring:
application:
name: spring-data-redis
data:
redis:
password: wangzhexiao
host: 49.233.186.253
port: 6379
jedis:
pool:
max-active: 10 # 最大连接
max-idle: 10 # 最大空闲连接
min-idle: 0 # 最小空闲连接
max-wait: 100 # 连接等待时间
client-type: jedis
2.4. RedisTemplate序列化/反序列化
RedisTemplate的两种序列化方案:
方案一:
-
自定义RedisTemplate
-
修改RedisTemplate的序列化器为GenericJackson2JsonRedisSerializer
使用该方法时有个不好的地方是会在我们的值里面,自动添加额外的类信息,会占用额外的内存资源开销:
方案二:
-
使用StringRedisTemplate
-
写入Redis时,手动把对象序列化为JSON
-
读取Redis时,手动把读取到的JSON反序列化为对象
使用该方式的话会避免第一种方案的问题,但是需要我们手动进行序列化/反序列化
2.4.1. 自定义RedisTemplate
在SpringDataRedis中,默认为我们使用JDK的序列化/反序列化方式,因此redis库中的key/value值会出现特殊编码,不便于我们查看。
Spring
提供了对RedisTemplate的序列化和反序列化支持,可以自定义序列化器来满足不同的需求。以下是一个使用RedisTemplate
进行序列化和反序列化的例子。在上述SpringBoot工程代码中新增下面的依赖:
XML
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
创建一个RedisConfig的配置类:
java
package com.example.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;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
// 创建RedisTemplate对象
RedisTemplate<String,Object> template = new RedisTemplate<>();
// 设置连接工厂
template.setConnectionFactory(redisConnectionFactory);
// 创建Json序列化工具
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// 设置key的序列化
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
// 设置value的序列化
template.setValueSerializer(jsonRedisSerializer);
// 返回
return template;
}
}
通过上述的代码配置,就能够对RedisTemplate 按照自身需求实现序列化/反序列化
2.4.2. 使用StringRedisTemplate
java
package com.example.springdataredisdemo;
import com.example.pojo.User;
import com.google.gson.Gson;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
@SpringBootTest
class SpringDataRedisDemoApplicationTests {
@Resource
private StringRedisTemplate stringRedisTemplate;
@Test
void contextLoads() {
User wzx = new User("王哲晓", 13);
Gson gson = new Gson();
stringRedisTemplate.opsForValue().set("people1", gson.toJson(wzx));
String json = stringRedisTemplate.opsForValue().get("people1");
System.out.println("people1: " + gson.fromJson(json, User.class));
}
}
XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>SpringDataRedisDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringDataRedisDemo</name>
<description>SpringDataRedisDemo</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>