@Cacheable 缓存值乱码如何解决?

已经配置过RedisTemplate

@Bean
public RedisTemplate redisTemplateInit() {
    //设置序列化Key的实例化对象
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    //设置序列化Value的实例化对象
    redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    return redisTemplate;
}

现在通过RedisTemplate直接设置值是没有问题的。

但是通过在方法上使用@Cacheable注解的方式缓存数据,key是正常的,value会出现一定的乱码,如下:
"xacxedx00x05tx00x1fStudent{name='test', age=22}"

是在redis中看是乱码,直接用代码取是正常的

请问有人遇到过这个问题吗?该如何解决

阅读 7.6k
2 个回答

是第二次请求接口使返回的数据乱码吗?

还是查询redis中的值时乱码。

我也在springboot的一个小项目中测试了一下,不过功能正常。

jpa:
    show-sql: true
  jackson:
    default-property-inclusion: non_null
  redis:
    host: 192.168.1.111
    port: 6379

对于使用StringRedisTemplate去存储token的AOP是正常的没我并没有配置什么,而是直接使用springboot的集成,

import org.springframework.data.redis.core.StringRedisTemplate;

然后我再一个请求商品的list时加了@Cacheable进行商品信息的缓存。

@GetMapping("/list")
    @Cacheable(cacheNames = "product",key = "1")
//    @Cacheable(cacheNames = "product", key = "#sellerId", condition = "#sellerId.length() > 3", unless = "#result.getCode() != 0")
    public ResultVO list(){
        
        ...
        ...
        ...
        return ResultVOUtil.success(productVOList);
    }

再页面与postman都是正常的显示数据,且控制台也跑出了sql(我这里执行两个sql操作)
请求结果
控制台信息
当我再次刷新时,sql并没有执行,而是去请求redis。
我去查看了redis,也正常存储进去了

redis可视化工具

你能具体说下你的bug问题还有复现下它的发生环境吗?

新手上路,请多包涵
时隔两年 我遇到了这个问题 搜到了楼主的帖子 最后发现太监了 
贴一下我找到的解决办法把  
`
//这里序列化解决@Cacheable 存值后value 显示字节码问题
@Bean  
public CacheManager cacheManager(RedisConnectionFactory factory) {  
    RedisSerializer<String> redisSerializer = new StringRedisSerializer();  
    Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);  
  
    //解决查询缓存转换异常的问题  
  ObjectMapper om = new ObjectMapper();  
    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);  
    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON\_FINAL);  
    jackson2JsonRedisSerializer.setObjectMapper(om);  
  
    // 配置序列化(解决乱码的问题)  
  RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()  
            .entryTtl(Duration.ZERO)//失效时间  
  .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))  
            .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))  
            .disableCachingNullValues();  
  
    RedisCacheManager cacheManager = RedisCacheManager.builder(factory)  
            .cacheDefaults(config)  
            .build();  
    return cacheManager;  
}
//这里序列化解决手动存值后value 显示字节码问题
// 这种 redisTemplate.opsForValue().set("wang","网");
@Bean  
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {  
    //设置序列化  
  //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)  
  Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);  
    ObjectMapper om = new ObjectMapper();  
    //指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public  
  om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);  
    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON\_FINAL);  
    jackson2JsonRedisSerializer.setObjectMapper(om);  
    //配置redisTemplate  
  RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();  
    // 配置连接工厂  
  redisTemplate.setConnectionFactory(lettuceConnectionFactory);  
    RedisSerializer stringSerializer = new StringRedisSerializer();  
    redisTemplate.setKeySerializer(stringSerializer);//key序列化  
  redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);//value序列化  
  redisTemplate.setHashKeySerializer(stringSerializer);//Hash key序列化  
  redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);//Hash value序列化  
  redisTemplate.afterPropertiesSet();  
    return redisTemplate;  
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题