Spring Cache自定义序列化解决乱码问题

Spring Cache数据缓存到 Redis中的 value是乱码问题(包含日期格式转换),主要是因为序列化方式导致的。

在这里插入图片描述
Spring Cache使用 Redis缓存管理器时,默认 value使用的是 JDK序列化值的方式,所以导致缓存的 value乱码的问题。

查看 RedisCacheManager和RedisCacheConfiguration源码:

在这里插入图片描述

解决方案:设置我们自定义的序列化方式。

一、Spring Cache自定义序列化

在上一篇文章的基础上配置序列化方式。

Spring Cache自定义缓存key和过期时间:https://blog.csdn.net/qq_42402854/article/details/139299549

1、创建自定义序列化方式

这里使用 Jackson2JsonRedisSerializer序列化方式实现,你也可以使用其他序列化方式。

    /**
     * 自定义 Jackson2JsonRedisSerializer序列化
     *
     * @return
     */
    private static RedisSerializer<Object> customJackson2JsonRedisSerializer() {
        ObjectMapper objectMapper = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有,包括private和public
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 必须设置序列化输入的类型,否则无法将JSON转化为对象,会转化成Map类型。类必须是非final修饰的,如果final修饰的类,比如String,Integer等会抛出异常
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);

        // 自定义ObjectMapper的时间处理模块
        JavaTimeModule javaTimeModule = new JavaTimeModule();

        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));

        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));

        objectMapper.registerModule(javaTimeModule);

        // 禁用将日期序列化为时间戳的行为
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        return jackson2JsonRedisSerializer;
    }

2、配置自定义序列化方式

通过源码发现缓存的 key使用的是 StringRedisSerializer序列化方式。你可以设置,也可以不设置。因为,对于 key的序列化,StringRedisSerializer也是我们常用的。

Spring Cache序列化配置赋值 SerializationPair对象。可以通过它构建。

RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer<T> serializer);

在我们自定义的 CustomRedisCacheManager类中添加下面代码。

    /**
     * @param name        must not be {@literal null}. 业务 Cache注解的value|cacheNames
     * @param cacheConfig can be {@literal null}.
     * @return
     */
    @Override
    protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) {
        Duration ttl = getTtlByCustomName(name);
        if (ttl == null) {
            // 如果自定义 TTL为空,则设置全局 TTL为7天。
            ttl = Duration.ofDays(7);
        }
        /**
         * Cache缓存配置
         */
        cacheConfig = cacheConfig
                .computePrefixWith(CUSTOM_CACHE_KEY_PREFIX) // 设置缓存key
                .entryTtl(ttl)  // 设置缓存的过期时间,查询不会更新过期时间
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.string())) // 缓存 key的序列化方式
                .serializeValuesWith(CUSTOM_JACKSON2JSON_REDIS_SERIALIZER_PAIR) // 缓存 value的序列化方式
        ;
        return super.createRedisCache(name, cacheConfig);
    }

    /**
     * 自定义序列化方式为json
     */
    private static final RedisSerializationContext.SerializationPair<Object> CUSTOM_JACKSON2JSON_REDIS_SERIALIZER_PAIR =
            RedisSerializationContext.SerializationPair
                    //.fromSerializer(new GenericJackson2JsonRedisSerializer());
                    .fromSerializer(customJackson2JsonRedisSerializer());

3、业务使用

    @Cacheable(value = "userCache_#120", key = "#id", unless = "#result==null")
    //@Cacheable(value = "userCache_", key = "#id", unless = "#result==null")
    //@Cacheable(value = "userCache_#0asa", key = "#id", unless = "#result==null")
    @Override
    public UserDTO getById(Long id) {
        if (id == null || id <= 0L) {
            return null;
        }
        UserDO userDO = userMapper.selectById(id);
        return do2DTO(userDO);
    }

在这里插入图片描述

– 求知若饥,虚心若愚。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/676575.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Java面试】十、微服务篇-分布式(下)

文章目录 1、分布式系统2、CAP定理3、Base理论4、分布式事务的解决方案&#xff1a;Seata4.1 Seata的XA模式4.2 Seata的AT模式4.3 Seata的TCC模式 5、分布式事务的解决方案&#xff1a;MQ6、分布式系统下&#xff0c;接口的幂等性6.1 数据库唯一索引6.2 token redis6.3 分布式…

MATLAB和物联网连载1:Internet of Things离你有多远?5行MATLAB的距离

MATLAB和物联网连载1:Internet of Things离你有多远?5行MATLAB的距离 原文&#xff1a;MATLAB和物联网连载1:Internet of Things离你有多远?5行MATLAB的距离 - 知乎 (zhihu.com) 来自俄罗斯的实习生在工作之余喜欢上网看点有的没的。有一天他突然发现了一个神奇的网站叫 T…

HTTP --tcp和keep-alive

TCP TCP连接 tcp/ip是全球计算机以及网络设备都在使用的一种常见的分组交换网络分层协议集&#xff0c;客户端可以打开一条tcp/ip连接&#xff0c;连接到可能运行在世界各地的服务器应用程序&#xff0c;一旦连接建立起来了&#xff0c;在客户端和服务器的计算机之间交换的报…

IntelliJ IDEA配置创建文件后自动生成注释字段,包括作者、日期和描述等信息。

效果 新建文件自动生成如下文档注释 配置如下&#xff1a; 打开setting 进行如下操作 粘贴的模板内容如下&#xff1a; /*** author developer_ZhangXinHua* date ${YEAR}/${MONTH}/${DAY}* desc ${DESCRIPTION}*/

Nios II 实现流水灯实验

Nios II 实现流水灯实验 一.硬件设计1.新建Quartus项目2. 设计Nios ii 二.软件设计 前言 实验目标&#xff1a; 学习 Quartus 、Platform Designer、Nios-II SBT 的基本操作&#xff1b;初步了解 SOPC 的开发流程&#xff0c;基本掌握 Nios-II 软核的定制方法&#xff1b;掌握 …

期权交易要怎么计算盈亏?期权盈亏平衡点是什么?

今天带你了解期权交易要怎么计算盈亏&#xff1f;期权盈亏平衡点是什么&#xff1f;期权盈利和亏损的计算公式取决于具体的交易策略和期权类型。 期权交易要怎么计算盈亏&#xff1f; 期权买方盈亏计算&#xff1a; 对于期权买方&#xff08;无论是认购期权还是认沽期权&…

逻辑门(与门、或门、非门、异或门)

一、实验目的 了解DE1-SOC开发板一些外设。 掌握常用组合逻辑门电路的基本原理。 学习Verilog HDL的基本语法。 学习使用ModelSim工具对设计的电路进行仿真&#xff0c;包括编写Testbench仿真代码&#xff0c;以及ModelSim工具的使用。 熟悉使用Quartus软件从创建Quartus工…

什么是Swagger UI ,swagger ui 的authorization怎么获取?

什么是Swagger UI Swagger UI 是一个用于可视化和交互式地展示API文档的工具。它是Swagger&#xff08;现称为OpenAPI&#xff09;生态系统的一部分&#xff0c;旨在帮助开发者和API用户更好地理解、测试和调试API。 主要功能和作用 1. API文档自动生成&#xff1a; Swagge…

【Java高级教程】集合部分

参考链接 一、 Java 数据结构 二、 Java 集合框架 三 Java ArrayList 四 Java LinkedList 五 Java HashSet 六 Java HashMap 七 Java Iterator&#xff08;迭代器&#xff09; 八 Java Object 类 ava Object 类是所有类的父类&#xff0c;也就是说 Java 的所有类都继承了 Obj…

常用ai模型和一些术语的科普

本文是早年浏览easyai.tech后留下的笔记。 文章目录 神经网络CNNRNNGANKNNCPU和GPU/TPUNLPNo free lunch theoremtransformer注意力机制自动编码器&#xff0c;自编码器GNN推荐系统附录NFL的两个例子 神经网络 水流&#xff0c;水龙头&#xff0c;流量阀。 可以回想CNN分类MNI…

StretchSense:将手部动作无缝集成到Xsens全身动捕系统中

在动画制作中逼真的手部动作可以大幅提升角色的情感表现能力&#xff0c;这将使观众更加轻易的走进角色&#xff0c;感受角色的情感变化并更加快速的了解角色的性格特点。如性格外向的角色将拥有更加复杂的手部动作表达。因此有效加强角色的手部动画真实度有助于吸引更多的观众…

基于Java+Vue智慧社区管理系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝1W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;还…

22-验证码的处理

验证码这种问题是比较头疼的&#xff0c;对于验证码的处理&#xff0c;不要去想破解方法&#xff0c;这个验证码本来就是为了防止别人自动化登录的。 目前最快速解决的三个手段&#xff1a; 去掉验证码&#xff1a;比较适合新开发但未上线的系统。设置万能码&#xff1a;比较适…

【GD32】06 - SPI (含ST7735S TFT-LCD屏幕驱动)

这篇文章我们看看GD32中如何实现SPI&#xff0c;软件SPI的话可以参考我之前的文章&#xff0c;把对应操作GPIO口的代码从STM32改成GD32就可以使用了。 【快速上手STM32】SPI通信协议&&1.8寸TFT-LCD&#xff08;ST7735S&#xff09;_tftlcdst7735和stm32-CSDN博客文章浏…

docker部署skywalking

skywalking版本下载 1&#xff1a;拉取skywalking的oap镜像(可以选择自己的版本&#xff0c;最好与ui&#xff0c;agent版本一致) docker pull apache/skywalking-oap-server:9.5.02&#xff1a;启动oap docker run -d -p 11800:11800 -p 12800:12800 --name sw_oap apache/…

HCIE数通,为啥是网工的“黄金标准”?

作为网络工程师&#xff0c;你不可能没听说过HCIE&#xff0c;也不可能没听过数通&#xff0c;也可能曾经考虑过要不要挑战这个认证。 HCIE数通为何被誉为网工的黄金标准&#xff1f;聊聊 01 什么是HCIE数通&#xff1f; HCIE数通认证是华为技术有限公司推出的一项高级别认证…

深度学习-05-反向传播理论知识

深度学习-05-反向传播理论知识 本文是《深度学习入门2-自製框架》 的学习笔记&#xff0c;记录自己学习心得&#xff0c;以及对重点知识的理解。如果内容对你有帮助&#xff0c;请支持正版&#xff0c;去购买正版书籍&#xff0c;支持正版书籍不仅是尊重作者的辛勤劳动&#xf…

使用 IPSET 添加 CDN 节点 IP(IPv4/IPv6)到防火墙白名单

明月的服务器一直使用的是 iptables,随着近几年 IPv6 的普及&#xff0c;明月切身体会到还是 IPSET 最方便了&#xff0c;无论你是 IPv4 还是 IPv6 都可以方便的管理&#xff0c;无论你是加入白名单还是黑名单&#xff0c;都非常的简单高效&#xff01;今天就参照明月自己的实操…

PyQt5串口测试工具

笔者经常会遇到使用上位机进行相关测试的场景&#xff0c;但现成的上位机并不能完全满足自己的需求&#xff0c;或是上位机缺乏使用说明。所以&#xff0c;自己写&#xff1f; 环境说明 pycharm 2023.2.25 python 3.10 anaconda 环境配置 conda create -n envsram ##…

Proxmox Backup Server 命名空间使用

作者&#xff1a;田逸&#xff08;formyz&#xff09; Proxmox Backup Server&#xff08;一下统称PBS&#xff09;从2.2版本开始&#xff0c;新增了命名空间这样一个功能。这个功能大大便利了多Proxmox VE集群或者单节点备份&#xff0c;在以前PBS版本中&#xff0c;如果有多个…