当使用@cacheable缓存数据遇到的序列化问题

1.问题:使用@cacheable注解报错信息如下,很明显是jackson序列化时出的错误

Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_ARRAY token[["com.xxx.xxx.xxxxxxx.response.SummaryLeftResponse",{"mainpName":null,"mainpType":null,"mainpValue":2,"mainpUnit":"PERCENT","vsType":"BULB","vsValue":null,"vsFlag":-1,"vsLeft":-2.5,"vsLeftFlag":-1,"vsLeftUnit":"PERCENT","vsRight":-6.5,"vsRightFlag":-1,"vsRightUnit":"PERCENT","tableTimeRatio":16.0,"tableCompletedRatio":2.7,"rightAry":"101,3785"}]]]"; line: 1, column: 365] (through reference chain: java.util.ArrayList[0]->com.xxx.xxx.xxxxxxx.response.SummaryLeftResponse["rightAry"])

2.导致问题是SummaryLeftResponse对象里有一个rightAry字段是string类型的,接收到的数据是123,212这样的,所以导致在使用@cacheable序列化错误

我的redisManager配置

// 分别创建String和JSON格式序列化对象,对缓存数据key和value进行转换 ,
RedisSerializer<String> strSerializer = new StringRedisSerializer();
// 解决查询缓存转换异常的问题
Jackson2JsonRedisSerializer jacksonSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jacksonSerializer.setObjectMapper(om);
//
String cacheKey = commonConfigService.getValueByKey("cache_key");
// 定制缓存数据序列化方式以及时效
final org.springframework.data.redis.cache.RedisCacheConfiguration redisCacheConfiguration = org.springframework.data.redis.cache.RedisCacheConfiguration.defaultCacheConfig()
        .computePrefixWith(cacheName -> cacheKey)
        .entryTtl(Duration.ofHours(12))
        .serializeKeysWith(RedisSerializationContext.SerializationPair
                .fromSerializer(strSerializer))
        .serializeValuesWith(RedisSerializationContext.SerializationPair
                .fromSerializer(jacksonSerializer))
        .disableCachingNullValues();
final RedisCacheManager cacheManager = RedisCacheManager.builder(connectionFactory)
        .cacheDefaults(redisCacheConfiguration)
        .build();
return cacheManager;

3.当我弃用Jackson2JsonRedisSerializer使用JDKJsonRedisSerializer时发现每个对象都要去实现一次Serializable感觉对象一多就很麻烦,还是放弃了,打算使用FastJson2JsonRedisSerialize试试,我的代码

package com.sgm.cadillac.common.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;

import java.nio.charset.Charset;


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

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

    private Class<T> clazz;

    /**
     * 设置白名单---非常重要********
     使用fastjson的时候:序列化时将class信息写入,反解析的时候,
     fastjson默认情况下会开启autoType的检查,相当于一个白名单检查,
     如果序列化信息中的类路径不在autoType中,
     反解析就会报com.alibaba.fastjson.JSONException: autoType is not support的异常
     可参考 https://blog.csdn.net/u012240455/article/details/80538540
     */
    static {
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
//        ParserConfig.getGlobalInstance().addAccept("com.sgm.cadillac.cockpit.response");
    }

    public FastJson2JsonRedisSerialize(Class clazz) {
        super();
        this.clazz = clazz;
    }


    /**
     * 序列化
     *
     * @param t
     * @return
     * @throws SerializationException
     */
    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (t == null) {
            return new byte[0];
        }
        try {
            return JSON.toJSONBytes(t, SerializerFeature.WriteClassName);
        } catch (Exception ex) {
            throw new SerializationException("Could not write JSON: " + ex.getMessage(), ex);
        }
    }

    /**
     * 反序列化
     *
     * @param bytes
     * @return
     * @throws SerializationException
     */
    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (null == bytes || bytes.length <= 0) {
            return null;
        }
        String str = new String(bytes, DEFAULT_CHARSET);
        T t = JSON.parseObject(str, clazz);
        return t;
    }
}

===============================================================

@Bean
public RedisSerializer fastJson2JsonRedisSerialize() {
    return new FastJson2JsonRedisSerialize<>(Object.class);
}
@Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        // 分别创建String和JSON格式序列化对象,对缓存数据key和value进行转换 ,
        RedisSerializer<String> strSerializer = new StringRedisSerializer();
        //序列化方式2
        FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);//JSONObject
        //
        String cacheKey = commonConfigService.getValueByKey("cache_key");
        RedisSerializationContext.SerializationPair<String> serializerKey = RedisSerializationContext.SerializationPair
                .fromSerializer(strSerializer);
        RedisSerializationContext.SerializationPair<Object> serializerValue = RedisSerializationContext.
                SerializationPair.fromSerializer(new FastJson2JsonRedisSerialize<>(Object.class));
//                SerializationPair.fromSerializer(fastJsonRedisSerializer);
        org.springframework.data.redis.cache.RedisCacheConfiguration defaultCacheConfig =
                org.springframework.data.redis.cache.RedisCacheConfiguration.defaultCacheConfig();
        defaultCacheConfig = defaultCacheConfig
                .computePrefixWith(cacheName -> cacheKey)
                .entryTtl(Duration.ofSeconds(100))
                .serializeKeysWith(serializerKey)
                .serializeValuesWith(serializerValue)
                .disableCachingNullValues();
        //初始化RedisCacheManager
        return new RedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory), defaultCacheConfig);
    }

4.使用了FastJson2JsonRedisSerialize序列化后还是出现问题,在我使用@Cacheable后

,发现反序列化的数据变成这样的,多了一个字符串数值,其实正确的是只有一组数组,这样很奇怪,为什么会出现这种问题呢?

5.临时处理,在反序列化重写方法里只取正确的那一条记录即可解决,治标不治本吧,希望知道具体原因的小伙伴留言帮忙解答下,或者提出更好的使用FastJson2JsonRedisSerialize处理方式

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值