SpringDataRedis快速入门

  • 1.SpringDataRedis简介
  • 2.RedisTemplate快速入门
  • 3.RedisSerializer
  • 4.StringRedisTemplate


1.SpringDataRedis简介

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis

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

Spring Data Redis和Spring版本 spring data reactive redis_User


2.RedisTemplate快速入门

引入依赖:

<!-- 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>

配置Redis:

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    lettuce:
      pool:
        max-active: 8 # 最大连接
        max-idle: 8 # 最大空闲连接
        min-idle: 1 # 最小空闲连接
        max-wait: 1000 # 连接等待时间

现在就可以来测试一下啦:

@SpringBootTest
class RedisPageApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    void contextLoads() {
        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set("ttl", 500);
        Object ttl = valueOperations.get("ttl");
        System.out.println(ttl);  // 500
    }
}

3.RedisSerializer

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

Spring Data Redis和Spring版本 spring data reactive redis_java_02

缺点:

  • 可读性差
  • 内存占用较大

这时候就需要我们设置序列化方式了:(使用RedisSerializer指定序列化方式)

因为要使用到JSON,先要引入jackson依赖:

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.14.2</version>
</dependency>

新增Redis配置类:

@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();
        // 设置key的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        // 设置value的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        return template;
    }
}

测试一下吧:

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

    @Test
    void contextLoads() {
        ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
        opsForValue.set("name", "王哥");
        Object name = opsForValue.get("name");
        System.out.println(name);  // 王哥
    }
}

这时就不会出现乱码现象了:

Spring Data Redis和Spring版本 spring data reactive redis_redis_03

现在来测试一下存储对象:(Redis会自动进行序列化和反序列化)

@Test
void contextLoads() {
    ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
    opsForValue.set("klza:user:1", new User(1, "dahezhiquanwuwu", 12));
    User user = (User) opsForValue.get("klza:user:1");
    System.out.println(user);  // User(id=1, name=dahezhiquanwuwu, age=12)
}

Spring Data Redis和Spring版本 spring data reactive redis_redis_04


4.StringRedisTemplate

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

Spring Data Redis和Spring版本 spring data reactive redis_redis_05

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

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

Spring Data Redis和Spring版本 spring data reactive redis_java_06

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

@SpringBootTest
class RedisPageApplicationTests {

    @Autowired
    private StringRedisTemplate redisTemplate;

    private static final ObjectMapper mapper = new ObjectMapper();

    @Test
    void contextLoads() throws JsonProcessingException {
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        User user = new User(1, "王伟", 27);
        // 手动序列化
        String s = mapper.writeValueAsString(user);
        opsForValue.set("klza:user:3", s);
        // 取数据,反序列化
        String suser = opsForValue.get("klza:user:3");
        User user1 = mapper.readValue(suser, User.class);
        System.out.println(user1);  // User(id=1, name=王伟, age=27)
    }
}