Springboot下RedisTemplate的两种序列化方式

本文介绍两种Redis序列化方案:自定义RedisTemplate与使用StringRedisTemplate。前者存在内存开销问题,后者通过手动序列化减少内存占用。提供测试代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、定义一个配置类,自定义RedisTemplate的序列化方式

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){
        // 创建RedisTemplate对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置连接工厂
        template.setConnectionFactory(connectionFactory);
        // 创建JSON序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer =
                new GenericJackson2JsonRedisSerializer();
        StringRedisSerializer stringRedisSerializer =
                new StringRedisSerializer();
        // 设置Key的序列化
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        // 设置Value的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        // 返回
        return template;
    }
}

测试类进行测试

@SpringBootTest
class RedisDemoApplicationTests {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Test
    void testString() {
        // 写入一条String数据
        redisTemplate.opsForValue().set("name", "虎哥");
        // 获取string数据
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println("name = " + name);
    }

    @Test
    void testObject() {
        User user = new User();
        user.setName("何雨泊");
        user.setTel(110);
        redisTemplate.opsForValue().set("user",user);
        System.out.println("name = " + user);
    }
}

测试存入字符串

在这里插入图片描述

测试存入对象

对象类:
在这里插入图片描述
测试结果如下,能将Java对象自动的序列化为JSON字符串,并且查询时能自动把JSON反序列化为Java对象。
不过,其中记录了序列化时对应的class名称,目的是为了查询时实现自动反序列化。这会带来额外的内存开销。
在这里插入图片描述

二、继续优化

这个问题的解决我们可以采用手动序列化的方式,换句话说,就是不借助默认的序列化器,而是我们自己来控制序列化的动作,同时,我们只采用String的序列化器,这样,在存储value时,我们就不需要在内存中就不用多存储数据,从而节约我们的内存空间。
在这里插入图片描述这种用法比较普遍,因此SpringDataRedis就提供了RedisTemplate的子类:StringRedisTemplate,它的key和value的序列化方式默认就是String方式。省去了我们自定义RedisTemplate的序列化方式的步骤,而是直接使用:

@SpringBootTest
public class RedisStringTests {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Test
    void testString() {
        // 写入一条String数据
        stringRedisTemplate.opsForValue().set("stringRedisTemplate:name", "虎哥");
        // 获取string数据
        Object name = stringRedisTemplate.opsForValue().get("name");
        System.out.println("name = " + name);
    }
	/*
	*手动进行序列化,比较麻烦
	*/
    @Test
    void testObject() throws JsonProcessingException{
        // 创建
        ObjectMapper mapper = new ObjectMapper();

        User user = new User();
        user.setName("何雨泊");
        user.setTel(110);
        // 手动序列化
        String json = mapper.writeValueAsString(user);
        stringRedisTemplate.opsForValue().set("stringRedisTemplate:user",json);

        String string = stringRedisTemplate.opsForValue().get("stringRedisTemplate:user");
        // 手动反序列化
        User user1 = mapper.readValue(string, User.class);
        System.out.println("name = " + user1);
    }
	/*
    * 利用hutool库内的JSONUtil工具类,省去手动序列化,库的依赖在下面
    * */
    @Test
    void testObject1() {
        User user = new User();
        user.setName("何雨泊");
        user.setTel(110);
        /*利用hutool库内的JSONUtil进行自动序列化,将user转json*/
        stringRedisTemplate.opsForValue().set("user", JSONUtil.toJsonStr(user));
        String userjson = stringRedisTemplate.opsForValue().get("user");
        /*将json转为bean对象*/
        User user1 = JSONUtil.toBean(userjson, User.class);
        System.out.println("name = " + user1);
    }
}

hutool库的依赖

        <!--hutool-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.17</version>
        </dependency>

测试结果:
在这里插入图片描述

三、总结

RedisTemplate的两种序列化实践方案:

  • 方案一(存在一定问题):

    • 自定义RedisTemplate
    • 修改RedisTemplate的序列化器为GenericJackson2JsonRedisSerializer
  • 方案二(对方案一进行优化):

    • 使用StringRedisTemplate
    • 写入Redis时,手动把对象序列化为JSON 或者 使用工具类JSONUtil进行序列化(推荐)
    • 读取Redis时,手动把读取到的JSON反序列化为对象
<think>我们参考用户提供的引用内容,特别是引用[2]和引用[4],它们提到了Spring Boot中RedisTemplate的默认序列化问题以及自定义序列化的方法。 用户需求:在Spring Boot中实现Redis数据的自定义序列化。 步骤: 1. 添加依赖(引用[5]提供了依赖配置) 2. 自定义RedisTemplate,主要设置序列化方式(引用[2]提到默认的RedisTemplate没有设置合适的序列化方式,引用[4]提到了使用JSON序列化) 3. 配置序列化器,例如使用Jackson2JsonRedisSerializer来序列化value为JSON字符串(引用[4]) 具体实现: 我们可以创建一个配置类,在其中定义RedisTemplate的Bean,并设置key和value的序列化方式。 注意:引用[3]中使用了RedisTemplate<String, String>,但用户需要自定义序列化,所以我们将使用自定义的序列化器。 示例配置类: ```java 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.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); // 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式) Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); // 解决查询缓存转换异常的问题 // 这里可以配置ObjectMapper,比如设置日期格式等,根据需求来 // ObjectMapper om = new ObjectMapper(); // om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); // jackson2JsonRedisSerializer.setObjectMapper(om); // 设置key和value的序列化方式 redisTemplate.setKeySerializer(new StringRedisSerializer()); // key采用String的序列化方式 redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); // value序列化方式采用jackson redisTemplate.setHashKeySerializer(new StringRedisSerializer()); // hash的key也采用String的序列化方式 redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); // hash的value采用jackson redisTemplate.afterPropertiesSet(); return redisTemplate; } } ``` 说明: - 我们使用StringRedisSerializer来序列化key,这样key就会以字符串形式存储,便于阅读。 - 使用Jackson2JsonRedisSerializer来序列化value,这样存储的值将是JSON格式。 - 如果需要序列化对象比较复杂,可能需要配置ObjectMapper(如注释部分),以避免转换异常。 另外,引用[4]中提到了一种在RedisSerializationContext中使用JSON序列化方式,但上面的配置是针对RedisTemplate的,这是两种不同的方式RedisTemplate和ReactiveRedisTemplateRedisCacheManager等)。这里我们按照用户需求,针对RedisTemplate进行配置。 测试: 可以像引用[3]中那样注入RedisTemplate进行测试,但注意类型要匹配,我们这里定义的是RedisTemplate<String, Object>。 测试代码示例: ```java @SpringBootTest public class RedisTest { @Autowired private RedisTemplate<String, Object> redisTemplate; @Test public void test() { User user = new User("张三", 25); redisTemplate.opsForValue().set("user:1", user); User user1 = (User) redisTemplate.opsForValue().get("user:1"); System.out.println(user1); } } ``` 注意:User类需要实现Serializable接口吗? 使用Jackson2JsonRedisSerializer不需要实现Serializable接口,因为它使用的是JSON序列化,而不是Java原生序列化。 但是,如果使用默认的JdkSerializationRedisSerializer,则对象必须实现Serializable接口(引用[2]提到过)。 因此,使用我们自定义的JSON序列化方式对象不需要实现Serializable接口。 相关问题: 根据用户的问题,生成一些相关问题,以帮助用户深入理解。 §§相关问题§§ 1. 如何在Spring Boot中配置RedisTemplate使用不同的序列化方式(如JSON、String等)? 2. 除了Jackson2JsonRedisSerializer,还有哪些常用的Redis序列化器? 3. 如何为Redis的hash类型数据单独配置序列化方式? 4. 自定义序列化后,如何确保与已经存储在Redis中的数据兼容? 5. 在Spring Boot中,除了自定义RedisTemplate,还有哪些方式可以实现自定义序列化(例如通过RedisCacheManager)?</think>### Spring Boot Redis 自定义序列化方法 在 Spring Boot 中实现 Redis 数据的自定义序列化,可通过配置自定义的 `RedisTemplate` 实现。以下是详细步骤: #### 1. 添加依赖 确保 `pom.xml` 包含 RedisJSON 序列化依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> ``` #### 2. 创建配置类 定义 `RedisConfig` 配置类,自定义序列化方式(以 JSON 为例): ```java 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.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); // Key 序列化为 String template.setKeySerializer(new StringRedisSerializer()); // Value 序列化JSON Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class); template.setValueSerializer(serializer); // Hash Key/Value 序列化 template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(serializer); template.afterPropertiesSet(); return template; } } ``` #### 3. 使用自定义序列化 注入 `RedisTemplate` 操作数据,对象无需实现 `Serializable`: ```java @Autowired private RedisTemplate<String, Object> redisTemplate; public void saveUser(User user) { // 自动序列化JSON redisTemplate.opsForValue().set("user:" + user.getId(), user); } public User getUser(String id) { // 自动反序列化对象 return (User) redisTemplate.opsForValue().get("user:" + id); } ``` #### 关键配置说明 1. **序列化器选择**: - `StringRedisSerializer`:处理 String 类型的 key - `Jackson2JsonRedisSerializer`:将对象转为 JSON 存储[^4] 2. **优势**: - 避免默认 JDK 序列化的二进制数据(可读性差) - 支持跨语言数据交换 - 对象无需实现 `Serializable` 接口[^2] #### 测试验证 ```java @Test void testCustomSerialization() { User user = new User("张三", 25); redisTemplate.opsForValue().set("test:user", user); User cachedUser = (User) redisTemplate.opsForValue().get("test:user"); System.out.println(cachedUser.getName()); // 输出 "张三" } ``` > **注意**:如果使用 `@Cacheable` 注解,需额外配置 `RedisCacheManager` 的序列化方式,原理类似[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值