![](/img/trans.png)
[英]java.sql.SQLException: Incorrect string value: '\xAC\xED\x00\x05sr...'
[英]Spring boot caching with redis,key have \xac\xed\x00\x05t\x00\x06
我想使用 Spring 缓存 @Cacheable 来管理缓存。 而真正的缓存是redis。
我的代码是这样的:
@PostMapping("/post")
@CachePut(value = "abc", key = "#key")
public String putInRedis(@RequestParam String key, @RequestParam String value) {
saveInDB(key, value);
return value;
}
@GetMapping("/get")
@Cacheable(value = "abc", key = "#key")
public String queryRedis(@RequestParam String key) {
return findByKey(key);
}
在我收到帖子请求之后
本地主机:8080/post?key=key&value=value
redis 服务器出现一个奇怪的key
127.0.0.1:6379> keys *
1) "abc:\xac\xed\x00\x05t\x00\x03key"
127.0.0.1:6379> GET "abc:\xac\xed\x00\x05t\x00\x03key"
"\xac\xed\x00\x05t\x00\x05value"
奇怪的redis-key-with-spring-data-jedis
如何设置@Cacheable 的 Serializer 像 StringRedisTemplate 默认值:
public StringRedisTemplate() {
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
setKeySerializer(stringSerializer);
setValueSerializer(stringSerializer);
setHashKeySerializer(stringSerializer);
setHashValueSerializer(stringSerializer);
}
我的 application.properties:
spring.redis.host=localhost
spring.redis.password=
spring.redis.port=6379
构建.gradle
group 'io.freezhan'
version '1.0-SNAPSHOT'
buildscript {
repositories {
maven {
url 'https://plugins.gradle.org/m2/'
}
}
dependencies {
classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.4.0.RELEASE'
}
}
task wrapper(type: Wrapper) {
gradleVersion = '2.13'
distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"
}
apply plugin: 'java'
apply plugin: 'spring-boot'
sourceCompatibility = 1.5
repositories {
mavenCentral()
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web") {
exclude module: "spring-boot-starter-tomcat"
}
compile("org.springframework.boot:spring-boot-starter-data-redis")
compile("org.springframework.boot:spring-boot-starter-jetty")
compile("org.springframework.boot:spring-boot-starter-actuator")
compile 'org.projectlombok:lombok:1.16.10'
testCompile("junit:junit")
}
创建一个Redis模板
private RedisTemplate<String, ?> createRedisTemplateForEntity() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
redisTemplate.setConnectionFactory(getRedisConnectionFactory());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
为什么要创建一个奇怪的字符串作为键?
密钥是根据方法中存在的参数属性创建的,该属性被注释为可缓存。 这就是spring从redis读取缓存值的方式。
就像mm759的答案:
自己将RedisCacheManager定义为bean。
此代码将解决我的问题:
package io;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* Created by freezhan on 16/9/5.
*/
@Configuration
public class CacheConfig {
@Autowired
private StringRedisTemplate redisTemplate;
@Bean
public CacheManager cacheManager() {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
return cacheManager;
}
}
和redis存储是这样的:
这是我的两分钱。 🪙🏛️
TL; 博士
假设您正在寻找一种解决方案来删除所有这些奇怪的键。 不要浪费时间编写单行 bash 解决方案。 这行不通, redis-cli KEYS "user*" | xargs redis-cli DEL
redis-cli KEYS "user*" | xargs redis-cli DEL
(来源: 如何删除密钥? )。 您的密钥是二进制格式的管道,它们不会产生预期的结果。 扩展创建密钥的脚本的功能以删除它们(Think Python、Java、Go 等)。 或者,如果您负担得起,则删除所有键redis-cli flushall
(来源: 如何使用 Redis 原子地删除与模式匹配的键
就将您的密钥作为二进制数据而言,我不确定有什么好处(重复,二进制密钥,而不是数据)。 因为,结果可能证明它的空间效率和时间效率低于预期,至少根据这些帖子, do-storing-plain-text-data-take-up-less-space-than-storing-the-等效混乱, are-binary-storage-methods-more-efficient-than-text-based-ones 。 当然,如果您有意转换了密钥。
如果您希望将密钥设为字符串格式,请在 Redis 模板上将密钥序列化器设置为StringRedisSerializer
,如@Rohith K的回答中所指出的。 这将使您能够使用上面引用的模式匹配命令来删除键。
redisTemplate.setKeySerializer(new StringRedisSerializer());
最后,这里有更多关于这些有趣的符号"\\xac\\xed\\x00\\x05t\\x00:"
是如何添加到您的 Redis 键的讨论:
我希望这篇文章可以为您节省一些时间。 快乐编码🔥
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.