2019独角兽企业重金招聘Python工程师标准>>>
##描述 使用springboot整合redis,使用默认的序列化配置,然后使用redis-client去查询时查询不到相应的key.
使用工具发现,key的前面多了\xAC\xED\x00\x05t\x00!这样一个串.
而且value也是不能直观可见的.
##问题所在 使用springdataredis,默认情况下是使用org.springframework.data.redis.serializer.JdkSerializationRedisSerializer这个类来做序列化.
org.springframework.data.redis.core.RedisTemplate代码块.
public void afterPropertiesSet() {
super.afterPropertiesSet();
boolean defaultUsed = false;
if (defaultSerializer == null) {
defaultSerializer = new JdkSerializationRedisSerializer(
classLoader != null ? classLoader : this.getClass().getClassLoader());
}
if (enableDefaultSerializer) {
if (keySerializer == null) {
keySerializer = defaultSerializer;
defaultUsed = true;
}
if (valueSerializer == null) {
valueSerializer = defaultSerializer;
defaultUsed = true;
}
if (hashKeySerializer == null) {
hashKeySerializer = defaultSerializer;
defaultUsed = true;
}
if (hashValueSerializer == null) {
hashValueSerializer = defaultSerializer;
defaultUsed = true;
}
}
if (enableDefaultSerializer && defaultUsed) {
Assert.notNull(defaultSerializer, "default serializer null and not all serializers initialized");
}
if (scriptExecutor == null) {
this.scriptExecutor = new DefaultScriptExecutor(this);
}
initialized = true;
}
解决
手动设置key的序列化方式为StringRedisSerializer,强制使用.
**由于spring不支持泛型注入,这样会导致所有的redisTemplate的key序列方式都为StringRedisSerializer. ** _同时,最好在序列化对象保存时候手动将其转为json串后存入redis.易于在可视化工具中直接查看对应value _
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(factory);
RedisSerializer stringRedisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息;
redisTemplate.setKeySerializer(stringRedisSerializer);
return redisTemplate;
}
其他的解决方案
使用GenericJackson2JsonRedisSerializer
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
这样Object类型的value数据也能在redis json可视化.
自定义自己的序列化
由于使用的是fastjson作为web的序列方式,想统一.于是自己实现了一个
public class FastJson2JsonRedisSerializer implements RedisSerializer {
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Class clazz;
static {
ParserConfig.getGlobalInstance().addAccept("这里是允许反序列的白名单包名");
}
public FastJson2JsonRedisSerializer() {
}
public FastJson2JsonRedisSerializer(Class clazz) {
super();
this.clazz = clazz;
}
public byte[] serialize(T t) {
if (t == null) {
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
public T deserialize(byte[] bytes) {
if (bytes == null || bytes.length <= 0) {
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
if(clazz==null){
return (T) JSON.parse(str);
}
return (T) JSON.parseObject(str, clazz);
}
}
注意
fastjson 的AutoType功能是存在重大漏洞的,在1.2.25后才修复.具体:
https://github.com/alibaba/fastjson/wiki/enable_autotype