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

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 【异常】springboot集成@Cacheable缓存乱码的问题解决方案

一、问题及现象

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

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

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

二、原因分析

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

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

三、解决方案

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

package com.iot.back.message.process.config;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
/**
 * <p>RedisConfig 此类用于:Redis相关配置,用于解决存入Redis中值乱码问题 </p>
 * <p>@author:hujm</p>
 * <p>@date:2022年08月18日 18:04</p>
 * <p>@remark:</p>
 */
@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
    @Bean
    public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {
        CacheProperties.Redis redisProperties = cacheProperties.getRedis();
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        // 序列化值
        config = config.serializeValuesWith(RedisSerializationContext.SerializationPair
                .fromSerializer(new GenericJackson2JsonRedisSerializer()));
        if (redisProperties.getTimeToLive() != null) {
            config = config.entryTtl(redisProperties.getTimeToLive());
        }
        if (redisProperties.getKeyPrefix() != null) {
            config = config.prefixKeysWith(redisProperties.getKeyPrefix());
        }
        if (!redisProperties.isCacheNullValues()) {
            config = config.disableCachingNullValues();
        }
        if (!redisProperties.isUseKeyPrefix()) {
            config = config.disableKeyPrefix();
        }
        return config;
    }
}

使用 @Cacheable 注解的类

package com.iot.back.message.process.rpc;
import com.iot.back.message.process.convert.DeviceBasicInfoConvert;
import com.iot.back.message.process.dto.DeviceBasicInfoDTO;
import com.iot.basic.iotsmarthome.api.client.device.DeviceCloudClient;
import com.iot.basic.iotsmarthome.api.response.device.DeviceBasicInfoResponse;
import com.iot.framework.core.response.CommResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
 * <p>DeviceBasicInfoRpc 此类用于:设备基本信息远程调用 </p>
 * <p>@author:hujm</p>
 * <p>@date:2022年05月23日 15:07</p>
 * <p>@remark:</p>
 */
@Slf4j
@Component
public class DeviceBasicInfoRpc {
    @Resource
    private DeviceCloudClient deviceCloudClient;
    @Cacheable(cacheNames = "back-process-service:cache", key = "#sn+':'+#deviceId", sync = true)
    public DeviceBasicInfoDTO getDeviceBasicInfo(String sn, Integer deviceId) {
        CommResponse<DeviceBasicInfoResponse> deviceBasicInfoCommResponse = deviceCloudClient.getDeviceBasicInfo(sn, deviceId);
        if (deviceBasicInfoCommResponse == null || deviceBasicInfoCommResponse.isFail()) {
            log.error("P0|DeviceBasicInfoRpc|getDeviceBasicInfo|调用设备云服务时,根据sn和deviceId获取设备基础信息失败!");
            return null;
        }
        DeviceBasicInfoResponse deviceBasicInfoResponse = deviceBasicInfoCommResponse.getData();
        return DeviceBasicInfoConvert.INSTANCE.convert2DeviceBasicInfoDTO(deviceBasicInfoResponse);
    }
}

完结!


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
3月前
|
缓存 Java Maven
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
|
1月前
|
easyexcel Java UED
SpringBoot中大量数据导出方案:使用EasyExcel并行导出多个excel文件并压缩zip后下载
在SpringBoot环境中,为了优化大量数据的Excel导出体验,可采用异步方式处理。具体做法是将数据拆分后利用`CompletableFuture`与`ThreadPoolTaskExecutor`并行导出,并使用EasyExcel生成多个Excel文件,最终将其压缩成ZIP文件供下载。此方案提升了导出效率,改善了用户体验。代码示例展示了如何实现这一过程,包括多线程处理、模板导出及资源清理等关键步骤。
|
5月前
|
缓存 NoSQL Java
避免缓存失效的三大杀手:缓存击穿、穿透与雪崩的解决方案
避免缓存失效的三大杀手:缓存击穿、穿透与雪崩的解决方案
106 0
|
2月前
|
人工智能 运维 安全
聚焦API安全未来,F5打造无缝集成的解决方案
聚焦API安全未来,F5打造无缝集成的解决方案
82 26
|
1月前
|
缓存 NoSQL 关系型数据库
缓存穿透以及解决方案
缓存穿透以及解决方案
34 0
|
1月前
|
存储 NoSQL Java
Spring Boot项目中使用Redis实现接口幂等性的方案
通过上述方法,可以有效地在Spring Boot项目中利用Redis实现接口幂等性,既保证了接口操作的安全性,又提高了系统的可靠性。
37 0
|
2月前
|
存储 SQL 分布式计算
Hologres 与阿里云生态的集成:构建高效的数据处理解决方案
【9月更文第1天】随着大数据时代的到来,数据处理和分析的需求日益增长。阿里云作为国内领先的云计算平台之一,提供了多种数据存储和处理的服务,其中Hologres作为一款实时数仓产品,以其高性能、高可用性以及对标准SQL的支持而受到广泛关注。本文将探讨Hologres如何与阿里云上的其他服务如MaxCompute、DataHub等进行集成,以构建一个完整的数据处理解决方案。
85 2
|
3月前
|
缓存 NoSQL Java
【Azure Redis 缓存 Azure Cache For Redis】Redis出现 java.net.SocketTimeoutException: Read timed out 异常
【Azure Redis 缓存 Azure Cache For Redis】Redis出现 java.net.SocketTimeoutException: Read timed out 异常
|
3月前
|
缓存 NoSQL 网络协议
【Azure Redis 缓存】Redisson 连接 Azure Redis出现间歇性 java.net.UnknownHostException 异常
【Azure Redis 缓存】Redisson 连接 Azure Redis出现间歇性 java.net.UnknownHostException 异常
|
3月前
|
缓存 NoSQL Java
【Azure Redis 缓存】定位Java Spring Boot 使用 Jedis 或 Lettuce 无法连接到 Redis的网络连通性步骤
【Azure Redis 缓存】定位Java Spring Boot 使用 Jedis 或 Lettuce 无法连接到 Redis的网络连通性步骤