0
点赞
收藏
分享

微信扫一扫

SpringDataRedis的序列化方式和StringRedisTemplate手动序列化详解

一.SpringDataRedis

之前新创建一个Spring项目,在进行配置完成redis和common-pool依赖:

1.引入依赖redis:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>

2.引入common-pool依赖:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

我们去yaml里配置redis链接配置:

spring:
  data:
    redis:
      database: 0
      port: 6379
      host: 127.0.0.1
      jedis:
        pool:
          min-idle: 0
          max-idle: 8
          max-active: 8
          max-wait: 100ms

配置设定他的库位置,端口号,ip地址,最大连接数,保活数,和最大延时等待时间。

去单元测试里:

@Autowired
private RedisTemplate redisTemplate;

@Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过 @Autowired的使用来消除 set ,get方法。

配置单元测试,我们存储一个键值对:

@Test
void testString() {
    redisTemplate.opsForValue().set("name","xiaozhu");
    Object name = redisTemplate.opsForValue().get("name");
    System.out.println("name"+name);
}

运行结果:

image-20230309090757184

RESP效果如下:

image-20230309090734434

1.1 SpringDataRedis总结

SpringDataRedis 的使用步骤:

1. 引入 spring-boot-starter-data-redis 依赖

2.在 application.yml 配置 Redis 信息

3.注入 RedisTemplate

1.2 SpringDataRedis的序列化方式

Red is Template 可以接收任意 Object 作为值写入 Red is, 只不过写入前会把 Object 序列化为字节形式, 默认是采用 JDK 序列化,得到的结果是这样的:

image-20230309092102028

缺点:

  • 可读性差
  • 内存占用较大
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory connectionFactory){
    RedisTemplate<String,Object> template = new RedisTemplate<>();
    template.setConnectionFactory(connectionFactory);
    GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
    template.setKeySerializer(RedisSerializer.string());
    template.setHashKeySerializer(RedisSerializer.string());
    template.setValueSerializer(jsonRedisSerializer);
    template.setHashValueSerializer(jsonRedisSerializer);
    return template;
}

创建RedisTemplate对象

RedisTemplate<String,Object> template = new RedisTemplate<>();

设置链接工厂

template.setConnectionFactory(connectionFactory);

创建JSON序列化工具

GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();

设置Key序列化:

template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());

设置Value的序列化:

template.setValueSerializer(jsonRedisSerializer);
template.setHashValueSerializer(jsonRedisSerializer);

返回

return template;

引入Jackson依赖

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.14.2</version>
</dependency>

运行单元测试:运行成功

image-20230309195159199

1.3User案例(序列化与反序列化)

新建User对象。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private String name;
    private Integer age;
}

写一个test测试集:

@Test
void testSaveUser(){
    redisTemplate.opsForValue().set("user:100",new User("上进小菜猪",21));
    User o=(User) redisTemplate.opsForValue().get("user:100");
}

运行结果:

image-20230310084911970

RESP截图:Json格式。

image-20230310084944612

输出运行结果,检测反序列化:

System.out.println("o="+o);

image-20230310085136724

二.StringRedisTemplate

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

image-20230310085418028

为了在反序列化时知道对象的类型,JSON 序列化器会将类的 class 类型写入 json 结果中,存入 Redis,会带来额外的内存开销。

为了节省内存空间,我们并不会使用 JSON 序列化器来处理 value,而是统一使用 String 序列化器,要求只能存储 String 类型的 key 和 value。当需要存储 Java 对象时,手动完成对象的序列化和反序列化。

思路如下:

image-20230310085621891

2.1 StringRedisTemplate 类

Spring 默认提供了一个 StringRedisTemplate 类,它的 key 和 value 的序列化方式默认就是 String 方式。省去了我们自义 RedisTemplate 的过程:

新建测试类:

RedisStringTests

建立:StringRedisTemplate对象

@Autowired
private StringRedisTemplate stringRedisTemplate;

测试类

@Test
void testString() {
    stringRedisTemplate.opsForValue().set("name","小猪");
    Object name = stringRedisTemplate.opsForValue().get("name");
    System.out.println("name"+name);
}

运行结果:

image-20230310090544763

单元测试集:

@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("user"+user1);
    
}

代码解释: 创建对象:

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);

运行结果如下: image-20230310091613974

image-20230310091619516

哈希举例:

    @Test
    void testHash(){
        stringRedisTemplate.opsForHash().put("user:400","name","上进小菜猪");
        stringRedisTemplate.opsForHash().put("user:400","age","21");

//        Map<Object,Object> enteies=stringRedisTemplate.opsForValue().entries();
        Map<Object,Object> enteies= stringRedisTemplate.opsForHash().entries("user:400");

        System.out.println("entries"+enteies);
    }

运行结果如下:

image-20230310092527476

2.2 总结

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

方案一: l.自定义 RedisTemplate 2.修改 RedisTemplate 的序列化器为 GenericJackson2 JsonRedisSerializer

方案二: 1.使用 StringRedisTemplate 2.写入 Redisl 时,手动把对象序列化为 JSON 3.读取 Redis 时,手动把读取到的 JSON 反序列化为对象

举报

相关推荐

0 条评论