依赖版本
- JDK 17
- Spring Boot 3.2.0
- Redisson 3.25.0
工程源码:Gitee
集成Redis步骤
导入依赖
<properties>
<redisson.version>3.25.0</redisson.version>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>${redisson.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
编写配置文件
# application.yml
spring:
# ======== Redis配置 ========
redis:
redisson:
file: classpath:redisson.yaml
# redisson.yaml
# 编码。默认值: org.redisson.codec.JsonJacksonCodec
codec: !<org.redisson.codec.Kryo5Codec> {}
# 线程池数量。默认值: 当前处理核数量 * 2
threads: 16
# Netty线程池数量。默认值: 当前处理核数量 * 2
nettyThreads: 32
# 传输模式。默认值: NIO
transportMode: "NIO"
# 监控锁的看门狗超时,单位:毫秒。默认值: 30000
lockWatchdogTimeout: 30000
# 是否保持订阅发布顺序。默认值: true
keepPubSubOrder: true
# Redisson 单实例配置
singleServerConfig:
# 节点地址。格式:redis://host:port
address: "redis://127.0.0.1:6379"
# 密码。默认值: null
password: null
# 数据库编号。默认值: 0
database: 0
# 客户端名称(在Redis节点里显示的客户端名称)。默认值: null
clientName: null
# 连接超时,单位:毫秒。默认值: 10000
connectTimeout: 10000
# 命令等待超时,单位:毫秒。默认值: 3000
timeout: 3000
# 命令失败重试次数。默认值: 3
retryAttempts: 3
# 命令重试发送时间间隔,单位:毫秒。默认值: 1500
retryInterval: 1500
# 最小空闲连接数。默认值: 32
connectionMinimumIdleSize: 24
# 连接池大小。默认值: 64
connectionPoolSize: 64
# 单个连接最大订阅数量。默认值: 5
subscriptionsPerConnection: 5
# 发布和订阅连接的最小空闲连接数。默认值: 1
subscriptionConnectionMinimumIdleSize: 1
# 发布和订阅连接池大小。默认值: 50
subscriptionConnectionPoolSize: 50
# DNS监测时间间隔,单位:毫秒。默认值: 5000
dnsMonitoringInterval: 5000
# 连接空闲超时,单位:毫秒。默认值: 10000
idleConnectionTimeout: 10000
编写Redis操作工具
import lombok.RequiredArgsConstructor;
import org.redisson.api.RAtomicDouble;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RBucket;
import org.redisson.api.RList;
import org.redisson.api.RMap;
import org.redisson.api.RScoredSortedSet;
import org.redisson.api.RSet;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* Redis工具类
*/
@Component
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class RedisService {
private final RedissonClient redissonClient;
// ============================= String类型操作 ============================
/**
* 将值存储到Redis中
*
* @param key 键
* @param value 值
*/
public <T> void setString(String key, T value) {
RBucket<T> bucket = redissonClient.getBucket(key);
bucket.set(value);
}
/**
* 将值存储到Redis中
*
* @param key 键
* @param value 值
* @param timeout 过期时间
* @param timeUnit 时间单位
*/
public <T> void setString(String key, T value, long timeout, TimeUnit timeUnit) {
RBucket<T> bucket = redissonClient.getBucket(key);
bucket.set(value, timeout, timeUnit);
}
/**
* 根据键获取Redis中的值
*
* @param key 键
* @return 值
*/
public <T> T getString(String key) {
RBucket<T> bucket = redissonClient.getBucket(key);
return bucket.get();
}
// ============================= Hash类型操作 ============================
/**
* 将值存储到Redis中
*
* @param key 键
* @param field hash键
* @param value 值
*/
public <T> boolean addToHash(String key, Object field, T value) {
RMap<Object, T> hash = redissonClient.getMap(key);
return hash.fastPut(field, value);
}
/**
* 将值存储到Redis中
*
* @param key 键
* @param field hash键
* @param value 值
* @param timeout 过期时间
* @param timeUnit 时间单位
*/
public <T> boolean addToHash(String key, Object field, T value, long timeout, ChronoUnit timeUnit) {
RMap<Object, T> hash = redissonClient.getMap(key);
boolean fastPut = hash.fastPut(field, value);
boolean expire = hash.expire(Instant.now().plus(timeout, timeUnit));
return fastPut && expire;
}
/**
* 根据键和Hash键获取Redis中的值
*
* @param key 键
* @param field hash键
* @return 值
*/
public <T> T getFromHash(String key, Object field) {
RMap<Object, T> hash = redissonClient.getMap(key);
return hash.get(field);
}
/**
* 根据键获取Redis中的值
*
* @param key 键
* @return 值
*/
public <T> Map<Object, T> getFromHash(String key) {
RMap<Object, T> hash = redissonClient.getMap(key);
return hash.readAllMap();
}
/**
* 根据键和Hash键更新Redis中的值
*
* @param key 键
* @param field hash键
* @param value 值
* @return 更新成功返回true,否则返回false
*/
public <T> boolean updateToHash(String key, Object field, T value) {
RMap<Object, T> hash = redissonClient.getMap(key);
return hash.fastReplace(field, value);
}
/**
* 根据Key,删除Hash类型的数据
*
* @param key 键
* @param hashKeys hash键
* @return 删除成功的数量
*/
public <T> long removeFromHash(String key, T... hashKeys) {
RMap<Object, T> hash = redissonClient.getMap(key);
return hash.fastRemove(hashKeys);
}
// ============================= List类型操作 ============================
/**
* 向List数据类型中添加值
*
* @param key 键
* @param value 值
*/
public <T> boolean addToList(String key, T value) {
RList<T> list = redissonClient.getList(key);
return list.add(value);
}
/**
* 向List数据类型中添加值
*
* @param key 键
* @param value 值
*/
public <T> boolean addToList(String key, List<T> value) {
RList<T> list = redissonClient.getList(key);
return list.addAll(value);
}
/**
* 向List数据类型中添加值
*
* @param key 键
* @param value 值
* @param timeout 过期时间
* @param timeUnit 时间单位
*/
public <T> boolean addToList(String key, T value, long timeout, ChronoUnit timeUnit) {
RList<T> list = redissonClient.getList(key);
list.add(value);
return list.expire(Instant.now().plus(timeout, timeUnit));
}
/**
* 从List数据类型中获取值
*
* @param key 键
* @param start 起始位置
* @param end 结束位置
* @return 值
*/
public <T> List<T> getFromList(String key, int start, int end) {
RList<T> list = redissonClient.getList(key);
return list.range(start, end);
}
/**
* 获取List数据类型中的所有值
*
* @param key 键
* @return 值
*/
public <T> List<T> getFromList(String key) {
RList<T> list = redissonClient.getList(key);
return list.readAll();
}
/**
* 移除集合左侧第一个元素
*
* @param key 键
*/
public void removeListLeft(String key) {
RList<Object> list = redissonClient.getList(key);
list.fastRemove(0);
}
/**
* 移除集合右侧第一个元素
*
* @param key 键
*/
public void removeListRight(String key) {
RList<Object> list = redissonClient.getList(key);
list.fastRemove(list.size() - 1);
}
/**
* 移除集合指定位置元素
*
* @param key 键
* @param index 索引
*/
public void removeFromList(String key, int index) {
RList<Object> list = redissonClient.getList(key);
list.fastRemove(index);
}
/**
* 移除集合指定元素
*
* @param key 键
* @param value 值
*/
public <T> boolean removeFromList(String key, T value) {
RList<T> list = redissonClient.getList(key);
return list.removeIf(o -> o.equals(value));
}
// ============================= Set类型操作 ============================
/**
* 添加值到Set数据类型中
*
* @param key 键
* @param value 值
*/
public <T> boolean addToSet(String key, T value) {
RSet<T> set = redissonClient.getSet(key);
return set.add(value);
}
/**
* 添加值到Set数据类型中
*
* @param key 键
* @param value 值
* @param timeout 过期时间
* @param timeUnit 时间单位
* @return 是否成功
*/
public <T> boolean addToSet(String key, T value, long timeout, ChronoUnit timeUnit) {
RSet<T> set = redissonClient.getSet(key);
boolean add = set.add(value);
boolean expire = set.expire(Instant.now().plus(timeout, timeUnit));
return add && expire;
}
/**
* 添加值到Set数据类型中
*
* @param key 键
* @param values 值
* @return 是否成功
*/
public <T> boolean addToSet(String key, List<T> values) {
RSet<T> set = redissonClient.getSet(key);
return set.addAll(values);
}
/**
* 添加值到Set数据类型中
*
* @param key 键
* @param values 值
* @param timeout 过期时间
* @param timeUnit 时间单位
* @return 是否成功
*/
public <T> boolean addToSet(String key, List<T> values, long timeout, ChronoUnit timeUnit) {
RSet<T> set = redissonClient.getSet(key);
set.addAllCounted(values);
return set.expire(Instant.now().plus(timeout, timeUnit));
}
/**
* 获取Set的所有元素。
*
* @param key 键
* @return 所有值
*/
public <T> Set<T> getFromSet(String key) {
RSet<T> set = redissonClient.getSet(key);
return set.readAll();
}
/**
* 从Set数据类型中删除值
*
* @param key 键
* @param values 值
*/
public <T> void removeFromSet(String key, List<T> values) {
RSet<T> set = redissonClient.getSet(key);
values.forEach(set::remove);
}
/**
* 从Set数据类型中删除值
*
* @param key 键
* @param value 值
*/
public <T> boolean removeFromSet(String key, T value) {
RSet<T> set = redissonClient.getSet(key);
return set.remove(value);
}
// ============================= ZSet类型操作 ============================
/**
* 添加值到ZSet数据类型中
*
* @param key 键
* @param value 值
* @param score 分值
*/
public <T> void addToZSet(String key, T value, double score) {
RScoredSortedSet<T> sortedSet = redissonClient.getScoredSortedSet(key);
sortedSet.add(score, value);
}
/**
* 在ZSet数据类型中添加值
*
* @param key 键
* @param value 值
* @param score 分值
* @param timeout 过期时间
* @param timeUnit 时间单位
*/
public <T> void addToZSet(String key, T value, double score, long timeout, ChronoUnit timeUnit) {
RScoredSortedSet<T> sortedSet = redissonClient.getScoredSortedSet(key);
sortedSet.add(score, value);
sortedSet.expire(Instant.now().plus(timeout, timeUnit));
}
/**
* 获取ZSet的范围元素。
*
* @param key 键
* @param start 起始位置
* @param end 结束位置
* @return Set类型的值
*/
public <T> Set<Object> getFromZSet(String key, int start, int end) {
RScoredSortedSet<T> sortedSet = redissonClient.getScoredSortedSet(key);
return new HashSet<>(sortedSet.valueRange(start, end));
}
/**
* 删除ZSet数据类型中的值
*
* @param key 键
* @param values 值
*/
public <T> void removeFromZSet(String key, List<T> values) {
RScoredSortedSet<T> sortedSet = redissonClient.getScoredSortedSet(key);
sortedSet.removeAll(values);
}
/**
* 删除ZSet数据类型中的值
*
* @param key 键
* @param value 值
*/
public <T> void removeFromZSet(String key, T value) {
RScoredSortedSet<T> sortedSet = redissonClient.getScoredSortedSet(key);
sortedSet.remove(value);
}
// ============================= Common ============================
/**
* 判断Key是否存在
*
* @param key 键
* @return 存在返回true,否则返回false
*/
public boolean exists(String key) {
return redissonClient.getBucket(key).isExists();
}
/**
* 删除Key
*
* @param key 键
*/
public boolean remove(String key) {
long delete = redissonClient.getKeys().delete(key);
return delete > 0;
}
/**
* 设置Key的过期时间
*
* @param key 键
* @param timeout 过期时间
* @param timeUnit 时间单位
* @return 设置成功返回true,否则返回false
*/
public boolean expire(String key, long timeout, ChronoUnit timeUnit) {
return redissonClient.getBucket(key).expire(Instant.now().plus(timeout, timeUnit));
}
/**
* 获取Key的过期时间
*
* @param key 键
* @return 过期时间
*/
public Long getExpire(String key) {
return redissonClient.getBucket(key).getExpireTime();
}
/**
* 递增操作
*
* @param key 键
* @param delta 增加的值
* @return 递增后的值,如果键不存在,则返回-1
*/
public long increment(String key, long delta) {
RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
return atomicLong.addAndGet(delta);
}
/**
* 递减操作
*
* @param key 键
* @param delta 减少的值
* @return 递减后的值,如果键不存在,则返回-1
*/
public long decrement(String key, long delta) {
RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
return atomicLong.decrementAndGet();
}
/**
* 递增操作
*
* @param key 键
* @param delta 增加的值
* @return 递增后的值,如果键不存在,则返回-1
*/
public double increment(String key, double delta) {
RAtomicDouble atomicDouble = redissonClient.getAtomicDouble(key);
return atomicDouble.addAndGet(delta);
}
/**
* 递减操作
*
* @param key 键
* @param delta 减少的值
* @return 递减后的值,如果键不存在,则返回-1
*/
public double decrement(String key, double delta) {
RAtomicDouble atomicDouble = redissonClient.getAtomicDouble(key);
return atomicDouble.decrementAndGet();
}
}
编写测试用例
import jakarta.annotation.Resource;
import jodd.util.ThreadUtil;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.time.LocalDateTime;
import java.util.List;
@Slf4j
@SpringBootTest
@DisplayName("Redis 集成测试类")
public class RedisApplicationTest {
@Resource
private RedisService redisService;
private static final String STRING_KEY = "redis:string";
private static final String LIST_KEY = "redis:list";
private static final String SET_KEY = "redis:set";
private static final String HASH_KEY = "redis:hash";
@Test
@DisplayName("Redis String 数据类型测试")
public void redisStringTest() {
log.info("Redis String 数据类型测试");
redisService.setString(STRING_KEY, LocalDateTime.now().toString());
String redisGetStringData = redisService.getString(STRING_KEY);
log.info("Redis String Get:{}", redisGetStringData);
boolean remove = redisService.remove(STRING_KEY);
log.info("Redis String Remove:{}", remove);
redisGetStringData = redisService.getString(STRING_KEY);
log.info("Redis String Get After Delete:{}", redisGetStringData);
}
@Test
@DisplayName("Redis List 数据类型测试")
public void redisListTest() {
log.info("Redis List 数据类型测试");
// 填充数据
List<Integer> list = Lists.newArrayList();
for (int i = 0; i < 5; i++) {
list.add(LocalDateTime.now().getNano());
ThreadUtil.sleep(5);
}
boolean addItemResult = redisService.addToList(LIST_KEY, LocalDateTime.now().getNano());
log.info("Redis List Add item:{}", addItemResult);
redisService.getFromList(LIST_KEY)
.forEach(s -> log.info("Redis List Get After Add Item:{}", s));
boolean addListDataResult = redisService.addToList(LIST_KEY, list);
log.info("Redis List Add List:{}", addListDataResult);
redisService.getFromList(LIST_KEY)
.forEach(s -> log.info("Redis List Get After Add List:{}", s));
redisService.getFromList(LIST_KEY, 0, 2)
.forEach(s -> log.info("Redis List Get By Index:{}", s));
log.info("Redis List Size Before Delete:{}", redisService.getFromList(LIST_KEY).size());
redisService.removeFromList(LIST_KEY, 0);
log.info("Redis List Size After Delete:{}", redisService.getFromList(LIST_KEY).size());
boolean remove = redisService.remove(LIST_KEY);
log.info("Redis List Remove:{}", remove);
}
@Test
@DisplayName("Redis Set 数据类型测试")
public void redisSetTest() {
log.info("Redis Set 数据类型测试");
// 填充数据
List<Integer> list = Lists.newArrayList();
for (int i = 0; i < 5; i++) {
list.add(LocalDateTime.now().getNano());
ThreadUtil.sleep(5);
}
boolean addItemResult = redisService.addToSet(SET_KEY, LocalDateTime.now().getNano());
log.info("Redis Set Add item:{}", addItemResult);
redisService.getFromSet(SET_KEY)
.forEach(s -> log.info("Redis Set Get After Add Item:{}", s));
boolean addListDataResult = redisService.addToSet(SET_KEY, list);
log.info("Redis Set Add List:{}", addListDataResult);
redisService.getFromSet(SET_KEY)
.forEach(s -> log.info("Redis Set Get After Add List:{}", s));
log.info("Redis Set Size Before Delete:{}", redisService.getFromSet(SET_KEY).size());
redisService.removeFromSet(SET_KEY, LocalDateTime.now().getNano());
log.info("Redis Set Size After Delete:{}", redisService.getFromSet(SET_KEY).size());
boolean remove = redisService.remove(SET_KEY);
log.info("Redis Set Remove:{}", remove);
}
@Test
@DisplayName("Redis Hash 数据类型测试")
public void redisHashTest() {
log.info("Redis Hash 数据类型测试");
Integer key = LocalDateTime.now().getNano();
boolean addItemResult = redisService
.addToHash(HASH_KEY, key, LocalDateTime.now().toString());
log.info("Redis Hash Add item:{}", addItemResult);
redisService.getFromHash(HASH_KEY)
.forEach((k, v) -> log.info("Redis Hash Get After Add Item:{} - {}", k, v.toString()));
log.info("Redis Hash Get By Key:{}", redisService.getFromHash(HASH_KEY, key).toString());
log.info("Redis Hash Size Before Delete:{}", redisService.getFromHash(HASH_KEY).size());
redisService.removeFromHash(HASH_KEY, key);
log.info("Redis Hash Size After Delete:{}", redisService.getFromHash(HASH_KEY).size());
boolean remove = redisService.remove(HASH_KEY);
log.info("Redis Hash Remove:{}", remove);
}
}