和 RedisTemplate 协作

使用 RedisTemplate 进行协作

问题描述

在之前的旧项目中,使用了 Spring Boot 框架,并通过 RedisTemplate 类操作数据库。RedisTemplate 在向 Redis 中写入数据时,会对 key 和 value 进行序列化。现在的问题是,如何使用 Java DB 的 Redis 工具读取由 RedisTemplate 序列化后的 key 和 value。

以下是 RedisTemplate 存入数据库中的示例数据:

key:

\xAC\xED\x00\x05t\x00\x05level

value:

\xAC\xED\x00\x05t\x01\xF0[{"levelDuration":10,"levelId":1,"levelName":"VIP","levelNote":"\xE5\x88\x9D\xE7\xBA\xA7\xE4\xBC\x9A\xE5\x91\x98","levelPermissions":"2:2:90:--","levelPrice":100.00,"levelTime":"2024-03-27 00:48:07"},{"levelDuration":10,"levelId":2,"levelName":"SVIP","levelNote":"\xE4\xB8\xAD\xE7\xBA\xA7\xE4\xBC\x9A\xE5\x91\x98","levelPermissions":"5:5:95:--","levelPrice":200.00,"levelTime":"2024-03-27 00:48:31"},{"levelDuration":10,"levelId":3,"levelName":"\xE7\x9A\x87\xE5\x86\xA0","levelNote":"\xE9\xAB\x98\xE7\xBA\xA7\xE4\xBC\x9A\xE5\x91\x98","levelPermissions":"10:10:90:--","levelPrice":500.00,"levelTime":"2024-03-27 00:49:12"}]

分析

默认情况下,RedisTemplate 使用 JdkSerializationRedisSerializer 进行序列化,它会将对象通过 Java 标准的序列化机制转换为字节数组,因此在 Redis 中会出现类似于 \xAC 这样的不可读二进制数据。

以下是一个示例代码,展示如何使用 JdkSerializationRedisSerializer 序列化一个字符串:

import org.junit.jupiter.api.Test;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;

import java.util.Arrays;

public class RedisKeyDeserializerTest {
  @Test
  public void keySerializerTest() {
    String str = "科学技术";
    JdkSerializationRedisSerializer serializer = new JdkSerializationRedisSerializer();
    byte[] serialize = serializer.serialize(str);
    System.out.println("key: " + Arrays.toString(serialize));
  }
}

使用 JdkSerializer

以下是一个使用 JdkSerializer 序列化数据的示例代码。此代码将对象序列化后存入 Redis,并验证序列化后的 key 和 value。

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import com.jfinal.kit.Kv;
import com.litongjava.redis.Cache;
import com.litongjava.redis.Redis;
import com.litongjava.redis.RedisPlugin;
import com.litongjava.redis.serializer.JdkSerializer;
import com.litongjava.tio.utils.json.JsonUtils;

public class JdkSerializerTest {
  @Test
  public void test() {
    RedisPlugin redisPlugin = new RedisPlugin("main", "192.168.1.2", 6379, 3000, "123456");
    redisPlugin.setSerializer(JdkSerializer.me);

    redisPlugin.start();

    List<Kv> kvs = new ArrayList<>();
    kvs.add(Kv.by("name", "唐僧").set("age", 30));
    kvs.add(Kv.by("name", "孙悟空").set("age", 1000));

    Cache cache = Redis.use();
    String json = JsonUtils.toJson(kvs);
    cache.set("student", json);

    String value = cache.get("student");
    System.out.println(value);
  }
}

测试结果表明,虽然 value 进行了序列化,但 key 仍然是字符串形式:

序列化后的 value:

\xAC\xED\x00\x05t\x00<[{"name":"\xE5\x94\x90\xE5\x83\xA7","age":30},{"name":"\xE5\xAD\x99\xE6\x82\x9F\xE7\xA9\xBA","age":1000}]

使用 KeyValueJdkSerializer

KeyValueJdkSerializer 会将 key 和 value 都进行序列化,然后存入 Redis 中。以下是一个示例代码:

package com.red.book.redis;

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import com.jfinal.kit.Kv;
import com.litongjava.redis.Cache;
import com.litongjava.redis.Redis;
import com.litongjava.redis.RedisPlugin;
import com.litongjava.redis.serializer.KeyValueJdkSerializer;
import com.litongjava.tio.utils.json.JsonUtils;

public class JdkSerializerTest {
  @Test
  public void test() {
    RedisPlugin redisPlugin = new RedisPlugin("main", "192.168.1.2", 6379, 3000, "123456");
    redisPlugin.setSerializer(KeyValueJdkSerializer.me);

    redisPlugin.start();

    List<Kv> kvs = new ArrayList<>();
    kvs.add(Kv.by("name", "唐僧").set("age", 30));
    kvs.add(Kv.by("name", "孙悟空").set("age", 1000));

    Cache cache = Redis.use();
    String json = JsonUtils.toJson(kvs);
    cache.set("student", json);

    String value = cache.get("student");
    System.out.println(value);
  }
}

使用 KeyValueJdkSerializer 序列化后的 key 如下:

\xAC\xED\x00\x05t\x00\x07student

最终的解析代码

最终,以下代码用于读取由 RedisTemplate 存入 Redis 中的序列化数据:

@Test
public void testWithSpringBoot() {
  RedisPlugin redisPlugin = new RedisPlugin("main", "192.168.1.2", 6379, 3000, "123456", 8);
  redisPlugin.setSerializer(KeyValueJdkSerializer.me);

  redisPlugin.start();
  Cache cache = Redis.use();
  String value = cache.get("level");
  System.out.println(value);
}

通过上述方法,可以成功读取由 RedisTemplate 序列化并存储在 Redis 中的数据。