Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.0k views
in Technique[技术] by (71.8m points)

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[]大概长这样
image

存入之后,从redis中读取出来就变成这样了
image
明显就不是一个东西,所以在反序列化的时候,就会报一个不太相关的错误:

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 (
, 
, ) 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 (
, 
, ) 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 (
, 
, ) 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)

请教到底是该怎么存进去?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

序列化和反序列化方式不一样
序列化用的jackson,反序列化用的对象流,肯定读不回来
配成一样的就行了


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...