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

在SpringBoot的redisTemplate在redis当中存入数据的时候,能看到key和value被序列化,我们基本上很难判断这个缓存是干什么用的,所以我们需要修复它:
缓存当中的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的可观测性提高了许多,好了下课

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot提供了对Redis的自动配置,可以方便地进行序列化和反序列化操作。下面是关于Spring Boot Redis序列化的介绍和示例代码: 1. Redis介绍: Redis是一个开源的内存数据结构存储系统,可以用作数据库、缓存和消息中间件。它支持多种数据结构,如字符串、哈希、列表、集合和有序集合。 2. 添加pom.xml依赖: 在Spring Boot项目的pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 3. 自动配置分析: Spring Boot会根据配置文件中的属性自动配置Redis连接工厂、Redis模板和Redis操作类等。 4. application.properties配置: 在application.properties文件中配置Redis相关属性,例如: ```properties spring.redis.host=localhost spring.redis.port=6379 spring.redis.password= ``` 5. 连接Redis测试: 可以使用RedisTemplate或者StringRedisTemplate来连接Redis并进行操作。以下是一个简单的示例代码: ```java @Autowired private RedisTemplate<String, Object> redisTemplate; public void set(String key, Object value) { redisTemplate.opsForValue().set(key, value); } public Object get(String key) { return redisTemplate.opsForValue().get(key); } ``` 6. 使用Jedis客户端: 除了使用RedisTemplate,还可以使用Jedis客户端来连接Redis。以下是一个示例代码: ```java @Autowired private JedisConnectionFactory jedisConnectionFactory; public void set(String key, String value) { try (Jedis jedis = jedisConnectionFactory.getConnection().getNativeConnection()) { jedis.set(key, value); } } public String get(String key) { try (Jedis jedis = jedisConnectionFactory.getConnection().getNativeConnection()) { return jedis.get(key); } } ``` 7. 自定义默认的序列化器: Spring Boot默认使用JdkSerializationRedisSerializer作为序列化器,可以通过自定义配置来修改默认的序列化器。以下是一个示例代码: ```java @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); template.setDefaultSerializer(new GenericJackson2JsonRedisSerializer()); return template; } } ``` 8. 序列化问题: 在使用Redis进行序列化时,需要注意对象的序列化和反序列化。可以使用Fastjson等第三方库来进行自定义序列化和反序列化操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值