当绝地武士使用Spring数据时,为什么数据会被存储在Redis中?
我在绝地使用Spring数据Redis。我正在尝试使用键当绝地武士使用Spring数据时,为什么数据会被存储在Redis中?,redis,spring-data,jedis,Redis,Spring Data,Jedis,我在绝地使用Spring数据Redis。我正在尝试使用键vc:${list\u id}存储哈希。我能够成功地插入到redis。但是,当我使用redis cli检查密钥时,我没有看到密钥vc:501381。相反,我看到的是\xac\xed\x00\x05t\x00\tvc:501381 为什么会发生这种情况?我如何改变这种情况 好的,在谷歌上搜索了一会儿,在上找到了帮助 这是因为Java序列化 redisTemplate的密钥序列化程序需要配置为StringRedisSerializer,即如下所
vc:${list\u id}
存储哈希。我能够成功地插入到redis。但是,当我使用redis cli检查密钥时,我没有看到密钥vc:501381
。相反,我看到的是\xac\xed\x00\x05t\x00\tvc:501381
为什么会发生这种情况?我如何改变这种情况 好的,在谷歌上搜索了一会儿,在上找到了帮助 这是因为Java序列化 redisTemplate的密钥序列化程序需要配置为
StringRedisSerializer
,即如下所示:
现在redis中的键是vc:501381
或者像@niconic所说的,我们也可以将默认序列化程序本身设置为字符串序列化程序,如下所示:
这意味着我们所有的键和值都是字符串。但是请注意,这可能不是最好的,因为您可能希望您的值不仅仅是字符串
如果您的值是一个域对象,那么您可以使用Jackson serializer并按照所述配置一个序列化程序,例如:
并将模板配置为:
您必须序列化要发送给redis的对象。下面是它的完整运行示例。它使用接口
DomainObject
作为Serializable
以下是步骤
1) 使用以下jar创建maven pom.xml
org.springframework
示例代码取自使用StringRedisTemplate
替换RedisTemplate
默认情况下,redisplate
使用Java序列化,stringredisplate
使用stringredisalizer
我知道这个问题已经有一段时间了,但最近我又对这个主题做了一些研究,所以我想在这里分享一下如何通过查看部分spring源代码来生成这个“半哈希”键
首先,Spring利用AOP解析注释,如@Cacheable、@cacheexecute或@CachePut
等。advice类是来自Spring上下文依赖项的CacheInterceptor
,它是CacheAspectSupport
的子类(也来自Spring上下文)。为了便于解释,我将使用@Cacheable
作为示例,在这里浏览部分源代码
调用注释为@Cacheable
的方法时,AOP会将其路由到此方法protectedcollection serializer=redisOperations.getValueSerializer()!=无效的redisOperations.getValueSerializer()文件
:(重新序列化程序)新的JdkSerializationRedisSerializer();
this.cacheMetadata=新的RedisCacheMetadata(名称、前缀);
this.cacheMetadata.setDefaultExpiration(到期);
this.redisOperations=redisOperations;
this.cacheValueAccessor=新的cacheValueAccessor(序列化程序);
如果(allowNullValues){
如果(redisOperations.getValueSerializer()实例为StringRedisSerializer
||redisOperations.getValueSerializer()实例为GenericToStringSerializer
||redisOperations.getValueSerializer()实例JacksonJSONRedisializer
||redisOperations.getValueSerializer()实例(Jackson2JSONRedisializer){
抛出新的IllegalArgumentException(String.format(
“Redis不允许具有空值的键”\\_(ツ)_/¯. "
+“所选%s不支持泛型类型处理,因此无法在启用allowNullValues的情况下使用。”
+“请使用其他重新序列化程序或禁用空值支持。”,
getShortName(redisOperations.getValueSerializer().getClass());
}
}
}
那么prefix
在这个RedisCache中的用法是什么呢?-->如构造函数中所示,它在这个语句中使用this.cacheMetadata=new RedisCacheMetadata(name,prefix);
,下面的RedisCacheMetadata
的构造函数显示了更多细节:
/**
*@param cacheName不能为{@literal null}或空。
*@param keyPrefix可以是{@literal null}。
*/
公共RedisCacheMatadata(字符串cacheName,字节[]键前缀){
Assert.hasText(cacheName,“cacheName不能为null或空!”);
this.cacheName=cacheName;
this.keyPrefix=keyPrefix;
StringRedisSerializer stringSerializer=新的StringRedisSerializer();
//持有密钥的集合的名称
this.setOfKnownKeys=usesKeyPrefix()?新字节[]{}:stringSerializer.serialize(cacheName+“~keys”);
this.cacheLockName=stringSerializer.serialize(cacheName+“~lock”);
}
此时,我们知道一些prefix参数已设置为RedisCacheMetadata
,但该前缀如何用于在Redis中形成键(例如,您提到的\xac\xed\x00\x05t\x00\tvc:501381)
基本上,CacheInterceptor
随后将向前调用方法private RedisCacheKey getRedisCacheKey(对象键)
来自上述RedisCache
对象,该对象使用RedisCacheMetadata
中的前缀和RedisOperation
中的键序列化器返回RedisCacheKey
的实例
私有RedisCacheKey getRedisCacheKey(对象密钥){
返回新的RedisCacheKey(key).usePrefix(this.cacheMetadata.getKeyPrefix())
.withKeySerializer(redisOperations.getKeySerializer());
}
到达这一点后,CacheInterceptor
的“pre”建议完成,它将继续执行由@Cacheable
注释的实际方法。在完成实际方法的执行后,它将执行