• 【异常】springboot集成@Cacheable缓存乱码的问题解决方案


    本文目录

    一、问题及现象

    二、原因分析

    三、解决方案


    一、问题及现象

    会把被标注的方法的返回值缓存到 Redis 中,相同的操作不会查数据库而是从缓存中获取数据。

    Springboot 集成 Redis,使用 @Cacheable 注解之后,把数据缓存到 Redis 中,数据是保存在Redis 中了,但是,通过 Redis 的可视化管理工具查看缓存的数据时,却发现 redis 中的 key 正常,但是 value 是乱码。如下图所示的乱码:

    修改过后,可以正常显示,如下图:

    二、原因分析

    其实出现上述乱码,一般情况都是没有配置 redis 序列化值导致的,而源码里的配置又没有默认,需要自己去实现。

    在网上有很多种写法,我搜索了很多都不适合自己,只有下面这一种可以正常。

    三、解决方案

    添加一个 Redis 的配置类即可。如下代码是我在项目中的代码,加上重启项目 Redis 缓存中的 value 即可正常显示。

    1. package com.iot.back.message.process.config;
    2. import org.springframework.boot.autoconfigure.cache.CacheProperties;
    3. import org.springframework.cache.annotation.CachingConfigurerSupport;
    4. import org.springframework.cache.annotation.EnableCaching;
    5. import org.springframework.context.annotation.Bean;
    6. import org.springframework.context.annotation.Configuration;
    7. import org.springframework.data.redis.cache.RedisCacheConfiguration;
    8. import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
    9. import org.springframework.data.redis.serializer.RedisSerializationContext;
    10. /**
    11. *

      RedisConfig 此类用于:Redis相关配置,用于解决存入Redis中值乱码问题

    12. *

      @author:hujm

    13. *

      @date:2022年08月18日 18:04

    14. *

      @remark

    15. */
    16. @EnableCaching
    17. @Configuration
    18. public class RedisConfig extends CachingConfigurerSupport {
    19. @Bean
    20. public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {
    21. CacheProperties.Redis redisProperties = cacheProperties.getRedis();
    22. RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
    23. // 序列化值
    24. config = config.serializeValuesWith(RedisSerializationContext.SerializationPair
    25. .fromSerializer(new GenericJackson2JsonRedisSerializer()));
    26. if (redisProperties.getTimeToLive() != null) {
    27. config = config.entryTtl(redisProperties.getTimeToLive());
    28. }
    29. if (redisProperties.getKeyPrefix() != null) {
    30. config = config.prefixKeysWith(redisProperties.getKeyPrefix());
    31. }
    32. if (!redisProperties.isCacheNullValues()) {
    33. config = config.disableCachingNullValues();
    34. }
    35. if (!redisProperties.isUseKeyPrefix()) {
    36. config = config.disableKeyPrefix();
    37. }
    38. return config;
    39. }
    40. }

    使用 @Cacheable 注解的类

    1. package com.iot.back.message.process.rpc;
    2. import com.iot.back.message.process.convert.DeviceBasicInfoConvert;
    3. import com.iot.back.message.process.dto.DeviceBasicInfoDTO;
    4. import com.iot.basic.iotsmarthome.api.client.device.DeviceCloudClient;
    5. import com.iot.basic.iotsmarthome.api.response.device.DeviceBasicInfoResponse;
    6. import com.iot.framework.core.response.CommResponse;
    7. import lombok.extern.slf4j.Slf4j;
    8. import org.springframework.cache.annotation.Cacheable;
    9. import org.springframework.stereotype.Component;
    10. import javax.annotation.Resource;
    11. /**
    12. *

      DeviceBasicInfoRpc 此类用于:设备基本信息远程调用

    13. *

      @author:hujm

    14. *

      @date:2022年05月23日 15:07

    15. *

      @remark

    16. */
    17. @Slf4j
    18. @Component
    19. public class DeviceBasicInfoRpc {
    20. @Resource
    21. private DeviceCloudClient deviceCloudClient;
    22. @Cacheable(cacheNames = "back-process-service:cache", key = "#sn+':'+#deviceId", sync = true)
    23. public DeviceBasicInfoDTO getDeviceBasicInfo(String sn, Integer deviceId) {
    24. CommResponse deviceBasicInfoCommResponse = deviceCloudClient.getDeviceBasicInfo(sn, deviceId);
    25. if (deviceBasicInfoCommResponse == null || deviceBasicInfoCommResponse.isFail()) {
    26. log.error("P0|DeviceBasicInfoRpc|getDeviceBasicInfo|调用设备云服务时,根据sn和deviceId获取设备基础信息失败!");
    27. return null;
    28. }
    29. DeviceBasicInfoResponse deviceBasicInfoResponse = deviceBasicInfoCommResponse.getData();
    30. return DeviceBasicInfoConvert.INSTANCE.convert2DeviceBasicInfoDTO(deviceBasicInfoResponse);
    31. }
    32. }

    完结!

  • 相关阅读:
    vue3响应式原理 vue3使用router vuex4 pinia的使用与传值 storeToRefs的使用
    【大学英语视听说上】绕口令练习
    Java Double isInfinite(double v)方法具有什么功能呢?
    从外卖小哥自学到阿里首席架构师,全靠这份“从零学架构宝典”真的太强了
    为你的网站加上和风天气插件
    景区住宿门票小程序开发解决方案
    2023最新Python学习路线+百部python基础视频
    非常好用的配音工具分享|做短视频旁白必备神器
    使用vue-sign插件
    计算机组成原理——指令系统(课程笔记)
  • 原文地址:https://blog.csdn.net/weixin_44299027/article/details/126430360