Initial project
This commit is contained in:
295
src/main/java/com/imyeyu/spring/util/Redis.java
Normal file
295
src/main/java/com/imyeyu/spring/util/Redis.java
Normal file
@@ -0,0 +1,295 @@
|
||||
package com.imyeyu.spring.util;
|
||||
|
||||
import com.imyeyu.spring.config.AbstractRedisConfig;
|
||||
import com.imyeyu.java.TimiJava;
|
||||
import com.imyeyu.java.bean.timi.TimiException;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.core.Cursor;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.ScanOptions;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* RedisTemplate 功能封装,简化 Redis 操作
|
||||
* <p>serializer 为该 RedisTemplate 的键的序列化操作,序列化解析器由 {@link AbstractRedisConfig} 提供
|
||||
*
|
||||
* @author 夜雨
|
||||
* @version 2021-11-21 09:58
|
||||
*/
|
||||
public class Redis<K, V> {
|
||||
|
||||
private final RedisSerializer<K> serializer;
|
||||
private final RedisTemplate<K, V> redis;
|
||||
|
||||
public Redis(RedisTemplate<K, V> redis, RedisSerializer<K> serializer) {
|
||||
this.redis = redis;
|
||||
this.serializer = serializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Redis 模板对象
|
||||
*
|
||||
* @return Redis 模板对象
|
||||
*/
|
||||
public RedisTemplate<?, ?> getRedis() {
|
||||
return redis;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加锁
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @param timeoutMS
|
||||
* @return true 为加锁成功
|
||||
*/
|
||||
public boolean lock(K key, V value, long timeoutMS) {
|
||||
Boolean lock = redis.opsForValue().setIfAbsent(key, value, timeoutMS, TimeUnit.MILLISECONDS);
|
||||
return lock != null && lock;
|
||||
}
|
||||
|
||||
public void releaseLock(K key) {
|
||||
destroy(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置存活时间
|
||||
*
|
||||
* @param key 键
|
||||
* @param ms 毫秒 TTL
|
||||
*/
|
||||
public void setExpire(K key, long ms) {
|
||||
redis.expire(key, Duration.ofMillis(ms));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取该数据 TTL
|
||||
*
|
||||
* @param key 键
|
||||
* @return 毫秒 TTL
|
||||
*/
|
||||
public long getExpire(K key) {
|
||||
return Objects.requireNonNullElse(redis.getExpire(key, TimeUnit.MILLISECONDS), -1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置数据并保持 TTL
|
||||
*
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
*/
|
||||
public void setAndKeepTTL(K key, V value) {
|
||||
Long expire = redis.getExpire(key, TimeUnit.MILLISECONDS);
|
||||
if (expire == null || expire <= 0) {
|
||||
// 判死
|
||||
destroy(key);
|
||||
} else {
|
||||
redis.opsForValue().set(key, value, Duration.ofMillis(expire));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置数据
|
||||
*
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @param ms 毫秒 TTL
|
||||
*/
|
||||
public void set(K key, V value, long ms) {
|
||||
redis.opsForValue().set(key, value, Duration.ofMillis(ms));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取值
|
||||
*
|
||||
* @param key 键
|
||||
* @return 值
|
||||
*/
|
||||
public V get(K key) {
|
||||
return redis.opsForValue().get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取值,强转为 String
|
||||
*
|
||||
* @param key 键
|
||||
* @return 值
|
||||
*/
|
||||
public String getString(K key) {
|
||||
return get(key).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取值,强转为 Boolean
|
||||
*
|
||||
* @param key 键
|
||||
* @return 值
|
||||
*/
|
||||
public Boolean is(K key) {
|
||||
return Boolean.parseBoolean(getString(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取值,强转为 Boolean 并取反
|
||||
*
|
||||
* @param key 键
|
||||
* @return 值
|
||||
*/
|
||||
public Boolean not(K key) {
|
||||
return !is(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否存在
|
||||
*
|
||||
* @param key 键
|
||||
* @return true 为存在
|
||||
*/
|
||||
public boolean has(K key) {
|
||||
return get(key) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对列表添加值
|
||||
*
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
*/
|
||||
public void add(K key, V value) {
|
||||
redis.opsForList().leftPush(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对列表批量添加值
|
||||
*
|
||||
* @param key 键
|
||||
* @param values 值
|
||||
*/
|
||||
@SafeVarargs
|
||||
public final void addAll(K key, V... values) {
|
||||
redis.opsForList().leftPushAll(key, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取为列表
|
||||
*
|
||||
* @param key 键
|
||||
* @return 列表
|
||||
*/
|
||||
public List<V> getList(K key) {
|
||||
return redis.opsForList().range(key, 0, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有数据列表
|
||||
*
|
||||
* @return 所有数据列表
|
||||
*/
|
||||
public Map<K, List<V>> getAllList() {
|
||||
Map<K, List<V>> r = new HashMap<>();
|
||||
List<K> ks = keys("*");
|
||||
for (int i = 0; i < ks.size(); i++) {
|
||||
r.put(ks.get(i), getList(ks.get(i)));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* 值为列表时查找是否存在某值
|
||||
*
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @return true 为存在
|
||||
*/
|
||||
public boolean contains(K key, V value) {
|
||||
return getList(key).contains(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有值
|
||||
*
|
||||
* @return 所有值
|
||||
* @throws TimiException 异常
|
||||
*/
|
||||
public List<V> values() {
|
||||
List<V> r = new ArrayList<>();
|
||||
List<K> keys = keys("*");
|
||||
for (K key : keys) {
|
||||
r.add(get(key));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有数据(包括键)
|
||||
*
|
||||
* @return 所有数据(包括键)
|
||||
*/
|
||||
public Map<K, V> map() {
|
||||
Map<K, V> r = new HashMap<>();
|
||||
List<K> ks = keys("*");
|
||||
for (int i = 0; i < ks.size(); i++) {
|
||||
r.put(ks.get(i), get(ks.get(i)));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取符合条件的 key
|
||||
*
|
||||
* @param pattern 表达式
|
||||
* @return keys
|
||||
*/
|
||||
public List<K> keys(String pattern) {
|
||||
List<K> keys = new ArrayList<>();
|
||||
scan(pattern, item -> {
|
||||
if (item != null) {
|
||||
keys.add(serializer.deserialize(item));
|
||||
}
|
||||
});
|
||||
return keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁对象
|
||||
*
|
||||
* @param key 键
|
||||
* @return true 为成功
|
||||
*/
|
||||
public boolean destroy(K key) {
|
||||
if (TimiJava.isNotEmpty(key) && has(key)) {
|
||||
Boolean isSucceed = redis.delete(key);
|
||||
return isSucceed != null && isSucceed;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** 删库 */
|
||||
public void flushAll() {
|
||||
Objects.requireNonNull(redis.getConnectionFactory()).getConnection().serverCommands().flushAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* scan 实现
|
||||
*
|
||||
* @param pattern 表达式
|
||||
* @param consumer 对迭代到的 key 进行操作
|
||||
*/
|
||||
private void scan(String pattern, Consumer<byte[]> consumer) {
|
||||
redis.execute((RedisConnection connection) -> {
|
||||
try (Cursor<byte[]> cursor = connection.keyCommands().scan(ScanOptions.scanOptions().count(Long.MAX_VALUE).match(pattern).build())) {
|
||||
cursor.forEachRemaining(consumer);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user