✨ redis 支持自定义动态前缀
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
package com.hccake.ballcat.common.redis.prefix;
|
||||
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* redis key前缀生成器
|
||||
*
|
||||
* @author huyuanzhi
|
||||
*/
|
||||
public interface IRedisPrefixConverter {
|
||||
|
||||
Logger LOGGER = LoggerFactory.getLogger(IRedisPrefixConverter.class);
|
||||
|
||||
/**
|
||||
* 生成前缀
|
||||
* @return 前缀
|
||||
*/
|
||||
String getPrefix();
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
* @return 是否启用
|
||||
*/
|
||||
boolean enable();
|
||||
|
||||
/**
|
||||
* 去除key前缀
|
||||
* @param bytes key字节数组
|
||||
* @return 原始key
|
||||
*/
|
||||
default byte[] unwrap(byte[] bytes) {
|
||||
int wrapLen;
|
||||
if (!enable() || bytes == null || (wrapLen = bytes.length) == 0) {
|
||||
return bytes;
|
||||
}
|
||||
String prefix = getPrefix();
|
||||
if (CharSequenceUtil.isBlank(prefix)) {
|
||||
LOGGER.warn("prefix converter is enabled,but method getPrefix returns blank result,check your implement!");
|
||||
return bytes;
|
||||
}
|
||||
byte[] prefixBytes = prefix.getBytes(StandardCharsets.UTF_8);
|
||||
int prefixLen = prefixBytes.length;
|
||||
int originLen = wrapLen - prefixLen;
|
||||
byte[] originBytes = new byte[originLen];
|
||||
System.arraycopy(bytes, prefixLen, originBytes, 0, originLen);
|
||||
return originBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给key加上固定前缀
|
||||
* @param bytes 原始key字节数组
|
||||
* @return 加前缀之后的key
|
||||
*/
|
||||
default byte[] wrap(byte[] bytes) {
|
||||
int originLen;
|
||||
if (!enable() || bytes == null || (originLen = bytes.length) == 0) {
|
||||
return bytes;
|
||||
}
|
||||
String prefix = getPrefix();
|
||||
if (CharSequenceUtil.isBlank(prefix)) {
|
||||
LOGGER.warn("prefix converter is enabled,but method getPrefix returns blank result,check your implement!");
|
||||
return bytes;
|
||||
}
|
||||
byte[] prefixBytes = prefix.getBytes(StandardCharsets.UTF_8);
|
||||
int prefixLen = prefixBytes.length;
|
||||
byte[] wrapBytes = new byte[prefixLen + originLen];
|
||||
System.arraycopy(prefixBytes, 0, wrapBytes, 0, prefixLen);
|
||||
System.arraycopy(bytes, 0, wrapBytes, prefixLen, originLen);
|
||||
return wrapBytes;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.hccake.ballcat.common.redis.prefix.impl;
|
||||
|
||||
import com.hccake.ballcat.common.redis.prefix.IRedisPrefixConverter;
|
||||
|
||||
/**
|
||||
* redis key前缀默认转换器
|
||||
*
|
||||
* @author huyuanzhi
|
||||
*/
|
||||
public class DefaultRedisPrefixConverter implements IRedisPrefixConverter {
|
||||
|
||||
private final String prefix;
|
||||
|
||||
public DefaultRedisPrefixConverter(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.hccake.ballcat.common.redis.serialize;
|
||||
|
||||
import com.hccake.ballcat.common.redis.prefix.IRedisPrefixConverter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
|
||||
|
||||
@@ -11,40 +12,22 @@ import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer
|
||||
@Slf4j
|
||||
public class PrefixJdkRedisSerializer extends JdkSerializationRedisSerializer {
|
||||
|
||||
private final String prefix;
|
||||
private final IRedisPrefixConverter redisPrefixConverter;
|
||||
|
||||
private final boolean enable;
|
||||
|
||||
public PrefixJdkRedisSerializer(String prefix) {
|
||||
this.prefix = prefix;
|
||||
this.enable = prefix != null && !"".equals(prefix);
|
||||
public PrefixJdkRedisSerializer(IRedisPrefixConverter redisPrefixConverter) {
|
||||
this.redisPrefixConverter = redisPrefixConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object deserialize(byte[] bytes) {
|
||||
Object origin = super.deserialize(bytes);
|
||||
if (enable && origin instanceof String) {
|
||||
String originKey = (String) origin;
|
||||
// 如果有全局前缀,则需要删除
|
||||
if (originKey.startsWith(prefix)) {
|
||||
originKey = originKey.substring(prefix.length());
|
||||
}
|
||||
return originKey;
|
||||
}
|
||||
else {
|
||||
return origin;
|
||||
}
|
||||
byte[] unwrap = redisPrefixConverter.unwrap(bytes);
|
||||
return super.deserialize(unwrap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serialize(Object object) {
|
||||
if (enable && object instanceof String) {
|
||||
String key = prefix + object;
|
||||
return super.serialize(key);
|
||||
}
|
||||
else {
|
||||
return super.serialize(object);
|
||||
}
|
||||
byte[] originBytes = super.serialize(object);
|
||||
return redisPrefixConverter.wrap(originBytes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.hccake.ballcat.common.redis.serialize;
|
||||
|
||||
import com.hccake.ballcat.common.redis.prefix.IRedisPrefixConverter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
@@ -13,32 +14,23 @@ import java.nio.charset.StandardCharsets;
|
||||
@Slf4j
|
||||
public class PrefixStringRedisSerializer extends StringRedisSerializer {
|
||||
|
||||
private final String prefix;
|
||||
private final IRedisPrefixConverter iRedisPrefixConverter;
|
||||
|
||||
private final boolean enable;
|
||||
|
||||
public PrefixStringRedisSerializer(String prefix) {
|
||||
public PrefixStringRedisSerializer(IRedisPrefixConverter iRedisPrefixConverter) {
|
||||
super(StandardCharsets.UTF_8);
|
||||
this.prefix = prefix;
|
||||
this.enable = prefix != null && !"".equals(prefix);
|
||||
this.iRedisPrefixConverter = iRedisPrefixConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deserialize(byte[] bytes) {
|
||||
String originKey = super.deserialize(bytes);
|
||||
// 如果有全局前缀,则需要删除
|
||||
if (enable && originKey != null && originKey.startsWith(prefix)) {
|
||||
originKey = originKey.substring(prefix.length());
|
||||
}
|
||||
return originKey;
|
||||
byte[] unwrap = iRedisPrefixConverter.unwrap(bytes);
|
||||
return super.deserialize(unwrap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serialize(String string) {
|
||||
if (enable && string != null) {
|
||||
string = prefix + string;
|
||||
}
|
||||
return super.serialize(string);
|
||||
public byte[] serialize(String key) {
|
||||
byte[] originBytes = super.serialize(key);
|
||||
return iRedisPrefixConverter.wrap(originBytes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.hccake.extend.redis.module;
|
||||
|
||||
import com.hccake.ballcat.common.redis.config.CachePropertiesHolder;
|
||||
import com.hccake.ballcat.common.redis.prefix.IRedisPrefixConverter;
|
||||
import com.hccake.ballcat.common.redis.serialize.PrefixStringRedisSerializer;
|
||||
import com.hccake.extend.redis.moudle.bloom.BloomRedisModuleHelper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -17,10 +17,10 @@ public class BloomRedisModuleHelperConfig {
|
||||
|
||||
@Bean
|
||||
@DependsOn("cachePropertiesHolder") // 防止 CachePropertiesHolder 初始化落后导致的空指针
|
||||
public BloomRedisModuleHelper bloomRedisModuleHelper() {
|
||||
public BloomRedisModuleHelper bloomRedisModuleHelper(IRedisPrefixConverter redisPrefixConverter) {
|
||||
BloomRedisModuleHelper bloomRedisModuleHelper = new BloomRedisModuleHelper(lettuceConnectionFactory);
|
||||
// 可选操作,配合 ballcat-spring-boot-starter-redis 的 key 前缀使用
|
||||
bloomRedisModuleHelper.setKeySerializer(new PrefixStringRedisSerializer(CachePropertiesHolder.keyPrefix()));
|
||||
bloomRedisModuleHelper.setKeySerializer(new PrefixStringRedisSerializer(redisPrefixConverter));
|
||||
return bloomRedisModuleHelper;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.hccake.extend.redis.module;
|
||||
|
||||
import com.hccake.ballcat.common.redis.prefix.IRedisPrefixConverter;
|
||||
import com.hccake.ballcat.common.redis.prefix.impl.DefaultRedisPrefixConverter;
|
||||
import com.hccake.ballcat.common.redis.serialize.PrefixStringRedisSerializer;
|
||||
import com.hccake.extend.redis.moudle.bloom.BloomInsertOptions;
|
||||
import com.hccake.extend.redis.moudle.bloom.BloomRedisModuleHelper;
|
||||
@@ -32,7 +34,8 @@ class RedisBloomDemoApplicationTests {
|
||||
bloomRedisModuleHelper = new BloomRedisModuleHelper(lettuceConnectionFactory);
|
||||
// 可选操作:配合 ballcat-spring-boot-starter-redis 提供的 PrefixStringRedisSerializer,可以给
|
||||
// redis key 添加默认的 key 前缀
|
||||
bloomRedisModuleHelper.setKeySerializer(new PrefixStringRedisSerializer("keyprefix:"));
|
||||
IRedisPrefixConverter redisPrefixConverter = new DefaultRedisPrefixConverter("keyprefix:");
|
||||
bloomRedisModuleHelper.setKeySerializer(new PrefixStringRedisSerializer(redisPrefixConverter));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -6,6 +6,8 @@ import com.hccake.ballcat.common.redis.config.CacheProperties;
|
||||
import com.hccake.ballcat.common.redis.config.CachePropertiesHolder;
|
||||
import com.hccake.ballcat.common.redis.core.CacheLock;
|
||||
import com.hccake.ballcat.common.redis.core.CacheStringAspect;
|
||||
import com.hccake.ballcat.common.redis.prefix.IRedisPrefixConverter;
|
||||
import com.hccake.ballcat.common.redis.prefix.impl.DefaultRedisPrefixConverter;
|
||||
import com.hccake.ballcat.common.redis.serialize.CacheSerializer;
|
||||
import com.hccake.ballcat.common.redis.serialize.JacksonSerializer;
|
||||
import com.hccake.ballcat.common.redis.serialize.PrefixJdkRedisSerializer;
|
||||
@@ -82,10 +84,10 @@ public class RedisAutoConfiguration {
|
||||
@DependsOn("cachePropertiesHolder")
|
||||
@ConditionalOnProperty(name = "ballcat.redis.key-prefix")
|
||||
@ConditionalOnMissingBean
|
||||
public StringRedisTemplate stringRedisTemplate() {
|
||||
public StringRedisTemplate stringRedisTemplate(IRedisPrefixConverter redisPrefixConverter) {
|
||||
StringRedisTemplate template = new StringRedisTemplate();
|
||||
template.setConnectionFactory(redisConnectionFactory);
|
||||
template.setKeySerializer(new PrefixStringRedisSerializer(CachePropertiesHolder.keyPrefix()));
|
||||
template.setKeySerializer(new PrefixStringRedisSerializer(redisPrefixConverter));
|
||||
return template;
|
||||
}
|
||||
|
||||
@@ -93,10 +95,10 @@ public class RedisAutoConfiguration {
|
||||
@DependsOn("cachePropertiesHolder")
|
||||
@ConditionalOnProperty(name = "ballcat.redis.key-prefix")
|
||||
@ConditionalOnMissingBean(name = "redisTemplate")
|
||||
public RedisTemplate<Object, Object> redisTemplate() {
|
||||
public RedisTemplate<Object, Object> redisTemplate(IRedisPrefixConverter redisPrefixConverter) {
|
||||
RedisTemplate<Object, Object> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(redisConnectionFactory);
|
||||
template.setKeySerializer(new PrefixJdkRedisSerializer(CachePropertiesHolder.keyPrefix()));
|
||||
template.setKeySerializer(new PrefixJdkRedisSerializer(redisPrefixConverter));
|
||||
return template;
|
||||
}
|
||||
|
||||
@@ -107,4 +109,12 @@ public class RedisAutoConfiguration {
|
||||
return new RedisHelper();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@DependsOn("cachePropertiesHolder")
|
||||
@ConditionalOnProperty(name = "ballcat.redis.key-prefix")
|
||||
@ConditionalOnMissingBean(IRedisPrefixConverter.class)
|
||||
public IRedisPrefixConverter redisPrefixConverter() {
|
||||
return new DefaultRedisPrefixConverter(CachePropertiesHolder.keyPrefix());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user