SpringDataRedis入门

2023/11/19 javaSpringSpringBootredis

# SpringDataRedis入门

SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中:

API 返回值类型 说明
redisTemplate.opsForValue() ValueOperations 操作String类型数据
redisTemplate.opsForHash() HashOperations 操作Hash类型数据
redisTemplate.opsForList() ListOperations 操作List类型数据
redisTemplate.opsForSet() SetOperations 操作Set类型数据
redisTemplate.opsForZSet() ZSetOperations 操作SortedSet类型数据
redisTemplate 通用的命令

各个*Operations类都封装了对应类型的操作

# 配置

在Springboot中提供依赖

        <!--    redis依赖    -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--    连接池依赖   -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
1
2
3
4
5
6
7
8
9
10

yaml配置:

spring:
  redis:
    port: 6379
    password: Lhh4850
    host: 192.168.101.66
    lettuce:
      pool:
        max-active: 8 #最大连接
        max-idle: 8 #最大空闲连接
        max-wait: 100 #最小空闲连接
        min-idle: 0 #连接等待时间
1
2
3
4
5
6
7
8
9
10
11

测试类:

@SpringBootTest
public class RedisTest {
    private final RedisTemplate redisTemplate;
    @Autowired
    public RedisTest(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
    @Test
    void testString(){
        redisTemplate.opsForValue().set("name","李四");
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println("name="+name);//name=李四
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 序列化问题

上文中加入了键名为name的键值对,但是redisTemplate.opsForValue().set()默认传递的是对象,会使用序列化的方式,调用jdk的序列化工具,所以我们在redis数据库中看到的是序列化后的键名和值

  • 缺点
    • 可读性差
    • 内存占用大

# 解决

改变RedisTemplate的序列化方式

以下为所有的序列化类:

image-20231025105413002

默认使用JdkSerializationRedisSerializer

如果键和值都是字符串,建议使用StringRedisSerializer

如果键是字符串,值是对象,建议使用GenericJackson2JsonRedisSerializer,它会把对象转换为JSON存储

# Redis配置类

  • 创建RedisTemplate对象
  • 设置连接工厂
  • 创建JSON序列化工具
  • 设置Key的序列化
  • 设置Value的序列化
  • 返回

配置类:

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory connectionFactory){
        // 创建RedisTemplate对象
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        // 设置连接工厂
        redisTemplate.setConnectionFactory(connectionFactory);
        // 创建JSON序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        //设置Key的序列化
        redisTemplate.setKeySerializer(RedisSerializer.string());
        redisTemplate.setHashKeySerializer(RedisSerializer.string());
        // 设置Value的序列化
        redisTemplate.setValueSerializer(jsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jsonRedisSerializer);
        // 返回
        return redisTemplate;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

关于加上GenericJackson2JsonRedisSerialize

# 报错解决:

加jackson依赖,哪怕是springboot

		<dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.15.3</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-jaxb-annotations</artifactId>
            <version>2.15.3</version>
        </dependency>
1
2
3
4
5
6
7
8
9
10

测试类:

@SpringBootTest
public class RedisTest {
    @Autowired
    private  RedisTemplate<String,Object> redisTemplate;


    @Test
    void testString(){
        redisTemplate.opsForValue().set("name","李四");
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println("name="+name);
    }
    @Test
    void testObject(){
        redisTemplate.opsForValue().set("name:100",new User("张三",18));
        Object name = redisTemplate.opsForValue().get("name:100");
        System.out.println("name="+name);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

数据库信息(name:100):

{
    "@class": "com.example.springdataredis.pojo.User",
    "name": "张三",
    "age": 18
}
1
2
3
4
5

通过@class来定位实体类,但是内存开销大

# 序列化生成@class造成的内存占用问题解决

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

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

@SpringBootTest
public class RedisStringTest {
    private final StringRedisTemplate stringRedisTemplate;
    private static final ObjectMapper mapper=new ObjectMapper();

    @Autowired
    public RedisStringTest(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Test
    void testString(){
        //字符串无需处理
        stringRedisTemplate.opsForValue().set("name","李四");
        Object name = stringRedisTemplate.opsForValue().get("name");
        System.out.println("name="+name);
    }
    @Test
    void testObject() throws JsonProcessingException {
        //手动序列化对象,通过Springboot自带的ObjectMapper
        String user = mapper.writeValueAsString(new User("张三", 18));
        //写入数据
        stringRedisTemplate.opsForValue().set("name:100",user);
        //获取数据
        String jsonUser = stringRedisTemplate.opsForValue().get("name:100");
        //反序列化,指定类型
        User ruser=mapper.readValue(jsonUser,User.class);
        System.out.println("user="+ruser);
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

数据库数据:

{
  "name": "张三",
  "age": 18
}
1
2
3
4

# 操作Hash类型

hset()变成了put()

hmset()变成了putAll()

get()还是一样

获取全部变成entries()

和java的hashmap方法名对应

测试类:

@SpringBootTest
public class RedisHashTest {
    private final StringRedisTemplate stringRedisTemplate;
    private static final ObjectMapper mapper=new ObjectMapper();

    @Autowired
    public RedisHashTest(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

 @Test
    void testHash(){
        HashOperations<String, Object, Object> template =stringRedisTemplate.opsForHash();
        template.put("user:400","name","李四");
        template.put("user:400","age","19");
        Map<Object, Object> users = template.entries("user:400");
        System.out.println(users);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
最后更新于: 2024/2/27 17:14:39