您的位置:首页 > 数据库 > Redis

springboot整合spring-data-redis中的坑

2017-04-24 14:31 751 查看
##描述
使用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<K>(this);
}

initialized = true;
}

解决

手动设置key的序列化方式为StringRedisSerializer,强制使用.

**由于spring不支持泛型注入,这样会导致所有的redisTemplate的key序列方式都为StringRedisSerializer.
**
_同时,最好在序列化对象保存时候手动将其转为json串后存入redis.易于在可视化工具中直接查看对应value
_

@Bean
public RedisTemplate<String, ?> redisTemplate(RedisConnectionFactory factory) {

RedisTemplate<String, Object> redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(factory);
RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息;
redisTemplate.setKeySerializer(stringRedisSerializer);
return redisTemplate;
}

其他的解决方案

使用GenericJackson2JsonRedisSerializer

redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

这样Object类型的value数据也能在redis json可视化.

自定义自己的序列化

由于使用的是fastjson作为web的序列方式,想统一.于是自己实现了一个

public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {

public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

private Class<T> clazz;

static {
ParserConfig.getGlobalInstance().addAccept("这里是允许反序列的白名单包名");
}
public FastJson2JsonRedisSerializer() {
}

public FastJson2JsonRedisSerializer(Class<T> 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息