springboot redis 如何存放对象?
问题描述
springboot 2.3.7 想存取java对象到redis中去,但是能存不能取,并且存进去的值看起来不太对。
redis 5.0.4
问题出现的环境背景及自己尝试过哪些方法
开始用 springboot 2.2.2 版本,不行,升级到2.3.7后还是不行。
用Jedis 替换默认的 Lettuce 也不行
按照网上的教程配置 RedisConfig 配置类,来序列化对象,不行
自己手动写了个序列化工具类不行
已单独尝试 Jedis 和 Lettuce 进行对象的存取,没毛病
### 相关代码
@Configuration
//@EnableCaching
//@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig {
@Bean("redisTemplates")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
// 配置 json 序列化器 - Jackson2JsonRedisSerializer
Jackson2JsonRedisSerializer jacksonSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
//ObjectMapper类是Jackson库的主要类。它提供一些功能将转换成Java对象匹配JSON结构
ObjectMapper objectMapper = new ObjectMapper();
//配置全局序列化参数
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jacksonSerializer.setObjectMapper(objectMapper);
// 创建并配置自定义 RedisTemplateRedisOperator
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
// 将 key 序列化成字符串
template.setKeySerializer(new StringRedisSerializer());
// 将 hash 的 key 序列化成字符串
template.setHashKeySerializer(new StringRedisSerializer());
// 将 value 序列化成 json
// template.setValueSerializer(jacksonSerializer);
template.setValueSerializer(new RedisObjectSerializer());
// 将 hash 的 value 序列化成 json
template.setHashValueSerializer(new RedisObjectSerializer());
template.afterPropertiesSet();
return template;
}
class RedisObjectSerializer implements RedisSerializer<Object> {
@Override
public Object deserialize(byte[] bytes) {
Object obj = SerializeUtil.unserialize(bytes);
return obj;
}
@Override
public byte[] serialize(Object object) {
byte[] bytes = SerializeUtil.serialize(object);
return bytes;
}
}
}
其中
template.setValueSerializer( jacksonSerializer);
不管是用自己的还是 jacksonSerializer都一样。
你期待的结果是什么?实际看到的错误信息又是什么?
跟了一下代码,发现存入redis之前序列化的byte[]
大概长这样
存入之后,从redis中读取出来就变成这样了
明显就不是一个东西,所以在反序列化的时候,就会报一个不太相关的错误:
java.io.StreamCorruptedException: invalid stream header: 00000000
at java.base/java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:946)
at java.base/java.io.ObjectInputStream.<init>(ObjectInputStream.java:385)
at cn.zj.service.util.SerializeUtil.unserialize(SerializeUtil.java:36)
at cn.zj.service.config.RedisConfig$RedisObjectSerializer.deserialize(RedisConfig.java:117)
at org.springframework.data.redis.core.AbstractOperations.deserializeValue(AbstractOperations.java:335)
at org.springframework.data.redis.core.AbstractOperations$ValueDeserializingRedisCallback.doInRedis(AbstractOperations.java:61)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:228)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:188)
at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:96)
at org.springframework.data.redis.core.DefaultValueOperations.get(DefaultValueOperations.java:53)
如果我用 jacksonSerializer
的话,报错如下
17:09:18.860 logback [http-nio-8090-exec-5] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [/zj] threw exception [Request processing failed; nested exception is org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Illegal character ((CTRL-CHAR, code 0)): only regular white space (r, n, t) is allowed between tokens
at [Source: (byte[])""[truncated 604356 bytes]; line: 1, column: 2]; nested exception is com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 0)): only regular white space (r, n, t) is allowed between tokens
at [Source: (byte[])""[truncated 604356 bytes]; line: 1, column: 2]] with root cause
com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 0)): only regular white space (r, n, t) is allowed between tokens
at [Source: (byte[])""[truncated 604356 bytes]; line: 1, column: 2]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1851)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:707)
at com.fasterxml.jackson.core.base.ParserMinimalBase._throwInvalidSpace(ParserMinimalBase.java:685)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._skipWSOrEnd(ReaderBasedJsonParser.java:2403)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:672)
at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:4664)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4513)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3572)
at org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer.deserialize(Jackson2JsonRedisSerializer.java:73)
请教到底是该怎么存进去?
回答
序列化和反序列化方式不一样
序列化用的jackson,反序列化用的对象流,肯定读不回来
配成一样的就行了