redis 支持自定义动态前缀

This commit is contained in:
b2baccline
2021-11-14 10:26:07 +08:00
parent f085bfbbcf
commit 370880b4b1
7 changed files with 142 additions and 50 deletions

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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());
}
}