SpringBoot自定义redisTemplate的key和value的序列化方式

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: SpringBoot自定义redisTemplate的key和value的序列化方式

在SpringBoot的redisTemplate在redis当中存入数据的时候,能看到key和value被序列化,我们基本上很难判断这个缓存是干什么用的,所以我们需要修复它:

解决这个问题我们需要自定义一个序列化器RedisJsonSerializerImpl,其中还有一个内部类:

/**
 * <p>
 * 序列化对象,将对象存入这个类中然后存入redis
 * </p>
 *
 * @author XiaoHH
 * @version 1.0
 * @date 2021-12-07 星期二 14:45:54
 */
static class SerializerObject {
    /**
     * 无参构造
     */
    public SerializerObject() {
    }
    /**
     * 全参构造
     *
     * @param className  对象的类名
     * @param jsonObject 将内容对象转换为json字符串之后的结果
     */
    public SerializerObject(String className, String jsonObject) {
        this.className = className;
        this.jsonObject = jsonObject;
    }
    /**
     * 对象的类名
     */
    private String className;
    /**
     * 将内容对象转换为json字符串之后的结果
     */
    private String jsonObject;
    public String getClassName() {
        return className;
    }
    public SerializerObject setClassName(String className) {
        this.className = className;
        return this;
    }
    public String getJsonObject() {
        return jsonObject;
    }
    public SerializerObject setJsonObject(String jsonObject) {
        this.jsonObject = jsonObject;
        return this;
    }
    /**
     * 将本对象转换为json格式
     *
     * @return 转换后的json
     */
    @Override
    public String toString() {
        return JSON.toJSONString(this);
    }
}

RedisJsonSerializerImpl实现了org.springframework.data.redis.serializer.RedisSerializer,并且实现下面两个方法,serialize方法定义了序列化对象(将对象从Java程序中存入缓存中),deserialize用户反序列化对象(将缓存中读取对象并转换为Java对象):

/**
 * 将对象序列化成一个 byte 数组
 *
 * @param t 对象的实例
 * @return 序列化后的结果
 * @throws SerializationException 可能会抛出序列化异常
 */
@Override
public byte[] serialize(T t) throws SerializationException {
    // 如果对象为空,那么就返回一个空的byte数组就好了
    if (null == t) return new byte[0];
    // 获取序列化后的对象
    String resultObject = new SerializerObject(t.getClass().getName(), JSON.toJSONString(t)).toString();
    return resultObject.getBytes(StandardCharsets.UTF_8);
}
/**
 * 将一个已经序列化好后的对象转换为一个真实的对象,并返回它
 *
 * @param bytes 序列化后的结果
 * @return 反序列化后的结果
 * @throws SerializationException 可能会抛出序列化异常
 */
@Override
public T deserialize(byte[] bytes) throws SerializationException {
    if (CollectionUtils.isNull(bytes)) return null;
    // 将其反序列化成一个字符串
    SerializerObject resultObject = JSON.parseObject(new String(bytes, StandardCharsets.UTF_8), SerializerObject.class);
    try {
        return JSON.parseObject(resultObject.jsonObject, (Type) Class.forName(resultObject.className));
    } catch (ClassNotFoundException e) {
        log.error("类未找到:" + resultObject.className, e);
        return null;
    }
}

类完整的代码如下:

package love.xiaohh.cost.utils.storage;
import com.alibaba.fastjson.JSON;
import love.xiaohh.cost.utils.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
/**
 * <p>
 * 存入redis的时候处理对象格式化的问题
 * </p>
 *
 * @author XiaoHH
 * @version 1.0
 * @date 2021-12-07 星期二 14:33:54
 * @file RedisJsonSerializerImpl.java
 */
public class RedisJsonSerializerImpl<T> implements RedisSerializer<T> {
    /**
     * 记录日志的对象
     */
    private static final Logger log = LoggerFactory.getLogger(RedisJsonSerializerImpl.class);
    /**
     * 将对象序列化成一个 byte 数组
     *
     * @param t 对象的实例
     * @return 序列化后的结果
     * @throws SerializationException 可能会抛出序列化异常
     */
    @Override
    public byte[] serialize(T t) throws SerializationException {
        // 如果对象为空,那么就返回一个空的byte数组就好了
        if (null == t) return new byte[0];
        // 获取序列化后的对象
        String resultObject = new SerializerObject(t.getClass().getName(), JSON.toJSONString(t)).toString();
        return resultObject.getBytes(StandardCharsets.UTF_8);
    }
    /**
     * 将一个已经序列化好后的对象转换为一个真实的对象,并返回它
     *
     * @param bytes 序列化后的结果
     * @return 反序列化后的结果
     * @throws SerializationException 可能会抛出序列化异常
     */
    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (CollectionUtils.isNull(bytes)) return null;
        // 将其反序列化成一个字符串
        SerializerObject resultObject = JSON.parseObject(new String(bytes, StandardCharsets.UTF_8), SerializerObject.class);
        try {
            return JSON.parseObject(resultObject.jsonObject, (Type) Class.forName(resultObject.className));
        } catch (ClassNotFoundException e) {
            log.error("类未找到:" + resultObject.className, e);
            return null;
        }
    }
    /**
     * <p>
     * 序列化对象,将对象存入这个类中然后存入redis
     * </p>
     *
     * @author XiaoHH
     * @version 1.0
     * @date 2021-12-12 星期日 09:45:54
     */
    static class SerializerObject {
        /**
         * 无参构造
         */
        public SerializerObject() {
        }
        /**
         * 全参构造
         *
         * @param className  对象的类名
         * @param jsonObject 将内容对象转换为json字符串之后的结果
         */
        public SerializerObject(String className, String jsonObject) {
            this.className = className;
            this.jsonObject = jsonObject;
        }
        /**
         * 对象的类名
         */
        private String className;
        /**
         * 将内容对象转换为json字符串之后的结果
         */
        private String jsonObject;
        public String getClassName() {
            return className;
        }
        public SerializerObject setClassName(String className) {
            this.className = className;
            return this;
        }
        public String getJsonObject() {
            return jsonObject;
        }
        public SerializerObject setJsonObject(String jsonObject) {
            this.jsonObject = jsonObject;
            return this;
        }
        /**
         * 将本对象转换为json格式
         *
         * @return 转换后的json
         */
        @Override
        public String toString() {
            return JSON.toJSONString(this);
        }
    }
}

然后我们定义一个RedisConfig,将设置这个序列化对象:

package love.xiaohh.cost.configurations;
import love.xiaohh.cost.constants.Constants;
import love.xiaohh.cost.utils.storage.RedisJsonSerializerImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
 * <p>
 * redis相关的配置类
 * </p>
 *
 * @author XiaoHH
 * @version 1.0
 * @date 2021-12-12 星期日 09:54:59
 * @file RedisConfig.java
 */
@Configuration
public class RedisConfig {
    /**
     * 定义redisTemplate对象,用于访问redis
     *
     * @param redisConnectionFactory redis的链接工厂,从Spring容器中获取
     * @return 自行配置好的redis访问对象
     */
    @Bean(Constants.REDISTEMPLATE)
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        // 缓存操作对象
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        // 设置链接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 键的序列化器
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        // 值的序列化器,这里我们用的是我们自己配置好的
        redisTemplate.setValueSerializer(new RedisJsonSerializerImpl<>());
        return redisTemplate;
    }

其中key的序列化器使用自带的 StringRedisSerializer,然后value序列化使用我们自定义的 RedisJsonSerializerImpl,这个类就定义好了,我们运行看看效果:

可以发现key和value的可观测性提高了许多,好了下课

相关实践学习
基于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
相关文章
|
5月前
|
Java
springboot字段注入@value细节
springboot字段注入@value细节
|
30天前
|
JSON 前端开发 数据格式
前端的全栈之路Meteor篇(五):自定义对象序列化的EJSON介绍 - 跨设备的对象传输
EJSON是Meteor框架中扩展了标准JSON的库,支持更多数据类型如`Date`、`Binary`等。它提供了序列化和反序列化功能,使客户端和服务器之间的复杂数据传输更加便捷高效。EJSON还支持自定义对象的定义和传输,通过`EJSON.addType`注册自定义类型,确保数据在两端无缝传递。
|
1月前
|
消息中间件 存储 Java
大数据-58 Kafka 高级特性 消息发送02-自定义序列化器、自定义分区器 Java代码实现
大数据-58 Kafka 高级特性 消息发送02-自定义序列化器、自定义分区器 Java代码实现
46 3
|
1月前
|
消息中间件 存储 分布式计算
大数据-61 Kafka 高级特性 消息消费02-主题与分区 自定义反序列化 拦截器 位移提交 位移管理 重平衡
大数据-61 Kafka 高级特性 消息消费02-主题与分区 自定义反序列化 拦截器 位移提交 位移管理 重平衡
23 1
|
2月前
|
JSON NoSQL Java
redis的java客户端的使用(Jedis、SpringDataRedis、SpringBoot整合redis、redisTemplate序列化及stringRedisTemplate序列化)
这篇文章介绍了在Java中使用Redis客户端的几种方法,包括Jedis、SpringDataRedis和SpringBoot整合Redis的操作。文章详细解释了Jedis的基本使用步骤,Jedis连接池的创建和使用,以及在SpringBoot项目中如何配置和使用RedisTemplate和StringRedisTemplate。此外,还探讨了RedisTemplate序列化的两种实践方案,包括默认的JDK序列化和自定义的JSON序列化,以及StringRedisTemplate的使用,它要求键和值都必须是String类型。
redis的java客户端的使用(Jedis、SpringDataRedis、SpringBoot整合redis、redisTemplate序列化及stringRedisTemplate序列化)
|
4月前
RedisTemplate序列化的问题
RedisTemplate序列化的问题
40 1
|
5月前
|
Java
springboot封装RedisTemplate
springboot封装RedisTemplate
|
5月前
|
JSON Java 数据格式
实现自定义序列化和反序列化控制的5种方式
实现自定义序列化和反序列化控制的5种方式
|
5月前
|
Java
springboot解决jackson序列化Long类型精度失效问题
springboot解决jackson序列化Long类型精度失效问题
138 0
|
17天前
|
JSON 数据格式 索引
Python中序列化/反序列化JSON格式的数据
【11月更文挑战第4天】本文介绍了 Python 中使用 `json` 模块进行序列化和反序列化的操作。序列化是指将 Python 对象(如字典、列表)转换为 JSON 字符串,主要使用 `json.dumps` 方法。示例包括基本的字典和列表序列化,以及自定义类的序列化。反序列化则是将 JSON 字符串转换回 Python 对象,使用 `json.loads` 方法。文中还提供了具体的代码示例,展示了如何处理不同类型的 Python 对象。
下一篇
无影云桌面