【Redis】StringRedisTemplate

一、引出问题

在上节我们已经学习了自定义 RedisSerializer 来实现全自动JSON的序列化和反序列化,这样依赖当我们向Redis中写入一个Java对象的时候就方便很多。

尽管JSON的序列化方式可以满足我们的需求,但依然存在一些问题,如图:

1653054602930

为了在反序列化时知道对象的类型,JSON序列化器会将类的class类型写入json结果中,并且这个字节码本身甚至比我数据类型还要长,存入Redis就会带来额外的内存开销。

但是也不能不写这个东西,序列化还好说,直接将对象转为字符串写就行了,但是反序列化的时候它怎么知道你这个JSON字符串要转成哪个类型的对象呢?因此这个东西是实现自动序列化必不可少的。


二、解决问题

因此如果你想减少内存的消耗,就不能使用JSON的序列化器来自动处理value,而是统一使用String序列化器,要求只能存储String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化。

如下图,有一个 User类 的对象需要往redis中存,此时可以手动序列化,我们手动在序列化的时候,就不需要将字节码写进去了,直接写类本身的属性就行了,然后再调用 set()方法 写入redis。

当我们要读取数据的时候,读出来的就是一个JSON字符串,它里面没有字节码,没有字节码就没有人帮你自动处理,此时就需要手动来处理,因为程序员自己知道我取出来的是哪个类型,此时就可以转为对应的类型了。

相当于是代码复杂了,加了两个手动处理的动作,但是就解决了刚刚内存占用的问题。

不过还有一点要注意的就是:既然说了要统一使用string的序列化器,也就是说之前的RedisTemplate需要统一的定义成用StringSerializer才行,因此需要重新定义RedisTemplate。

1653054744832

这里告诉大家一个好消息,不需要你重新定义,因为SpringDataRedis就提供了RedisTemplate的子类:StringRedisTemplate,它的key和value的序列化方式默认就是String方式。

省去了我们自定义RedisTemplate的序列化方式的步骤,而是直接使用StringRedisTemplate。


三、代码实现

@SpringBootTest
class RedisStringTests {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

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

    // ObjectMapper是SpringMVC中默认使用的JSON处理工具,因此这里就用它了,跟以前接触的fastjson是一样的,它的作用就是将对象转成JSON,这里当然也可以使用fastjson
    private static final ObjectMapper mapper = new ObjectMapper();

    // 存对象
    @Test
    void testSaveUser() throws JsonProcessingException {
        // 创建对象
        User user = new User("虎哥", 21);
        // 手动序列化,这里可能会有异常,碰见异常直接往外面抛即可
        String json = mapper.writeValueAsString(user);
        // 写入数据
        stringRedisTemplate.opsForValue().set("user:200", json);

        // 获取数据的时候默认就是字符串
        String jsonUser = stringRedisTemplate.opsForValue().get("user:200");
        // 手动反序列化
        User user1 = mapper.readValue(jsonUser, User.class);
        System.out.println("user1 = " + user1);
    }
}

此时我们再来看一看存储的数据,小伙伴们就会发现那个class数据已经不在了,节约了我们的空间~

image-20240524071533691

四、总结

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

  • 方案一:

    • 自定义RedisTemplate
    • 修改RedisTemplate的序列化器为GenericJackson2JsonRedisSerializer
    • 弊端:会占用额外空间,用来记录class字段
  • 方案二:

    • 使用StringRedisTemplate
    • 写入Redis时,手动把对象序列化为JSON
    • 读取Redis时,手动把读取到的JSON反序列化为对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值