SpringBoot 中应该怎样使用 Redis ?

环境信息

  • JDK 版本信息

  1.8

  • SpringBoot 版本、依赖信息

  org.springframework.boot
  spring-boot-starter-parent
  2.0.2.RELEASE
  

我们在 SpringBoot 中使用 Redis 时,会引入如下的 redis starter


  org.springframework.boot
  spring-boot-starter-data-redis

这个 starter 引入了 jedis 和 spring-data-redis 两个与 redis 核心的包。

一些核心类的定义

  • RedisConnection

RedisConnection 处理了与 redis 后端的通信。它提供了底层的方法,可以与redis通信,这些方法的输入和返回都是二进制的值,即 byte[](字节数组)。 如果需要直接使用 RedisConnection,则需要在调用方法时,自己处理序列化和反序列化的问题。

  • RedisTemplate

与 RedisConnection 相比,RedisTemplate 提供了较为抽象的方法。我们在使用 RedisTemplate 时,通常需要自己去指定 key 和 value 的序列化器。如果没有指定,则使用默认的 JdkSerializationRedisSerializer(JDK 的序列化策略),可以查看其源码如下:

public class RedisTemplate extends RedisAccessor implements RedisOperations, BeanClassLoaderAware {

    ...

    @SuppressWarnings("rawtypes") private @Nullable RedisSerializer keySerializer = null;
    @SuppressWarnings("rawtypes") private @Nullable RedisSerializer valueSerializer = null;
    @SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashKeySerializer = null;
    @SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashValueSerializer = null;
    private RedisSerializer stringSerializer = new StringRedisSerializer();

  ...

    @Override
    public void afterPropertiesSet() {

        super.afterPropertiesSet();

        boolean defaultUsed = false;

        if (defaultSerializer == null) {

            defaultSerializer = new JdkSerializationRedisSerializer(
                    classLoader != null ? classLoader : this.getClass().getClassLoader());
        }

        ...

        initialized = true;
}
  • StringRedisTemplate

最常用的 redis 客户端,用于存取 key 和 value 都是字符串类型的数据。默认采用 String 的序列化策略(StringRedisSerializer),可以查看其源码如下:

public class StringRedisTemplate extends RedisTemplate {

    /**
     * Constructs a new StringRedisTemplate instance. {@link #setConnectionFactory(RedisConnectionFactory)}
     * and {@link #afterPropertiesSet()} still need to be called.
     */
    public StringRedisTemplate() {
        RedisSerializer stringSerializer = new StringRedisSerializer();
        setKeySerializer(stringSerializer);
        setValueSerializer(stringSerializer);
        setHashKeySerializer(stringSerializer);
        setHashValueSerializer(stringSerializer);
    }

  ...
}

RedisConnection、RedisTemplate 和 StringRedisTemplate 的使用实例

  • Java Object(CityInfo)定义
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * 

城市信息

* Created by Qinyi. */ @Data @Builder @NoArgsConstructor @AllArgsConstructor public class CityInfo implements Serializable { /** 城市 */ private String city; /** 经度 */ private Double longitude; /** 纬度 */ private Double latitude; }
  • Redis 的配置类:RedisConfig
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * 

Redis 配置

* Created by Qinyi. */ @Configuration public class RedisConfig { private final RedisConnectionFactory redisConnectionFactory; @Autowired public RedisConfig(RedisConnectionFactory redisConnectionFactory) { this.redisConnectionFactory = redisConnectionFactory; } /** *

实例化 RedisConnection

* SpringBoot 会自动实例化 RedisConnectionFactory, 但是不会自动实例化 RedisConnection * */ @Bean("RedisConnection") RedisConnection getConn(){ return redisConnectionFactory.getConnection(); } /** *

配置 RedisTemplate key/value 的序列化方式

* */ @Bean("RedisTemplate") RedisTemplate getRedisTemplate(RedisConnectionFactory factory) { RedisTemplate template = new RedisTemplate<>(); // RedisTemplate key/value 默认的序列化策略 JdkSerializationRedisSerializer redisSerializer = new JdkSerializationRedisSerializer(); // StringRedisTemplate key/value 默认的序列化策略 RedisSerializer stringSerializer = new StringRedisSerializer(); template.setConnectionFactory(factory); template.setKeySerializer(stringSerializer); template.setValueSerializer(redisSerializer); return template; } }
  • 测试用例:RedisOpTest
import com.alibaba.fastjson.JSON;
import com.imooc.ad.Application;
import com.imooc.ad.vo.CityInfo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.test.context.junit4.SpringRunner;

import java.nio.charset.StandardCharsets;

/**
 * 

Redis 操作测试用例

* Created by Qinyi. */ @RunWith(SpringRunner.class) @SpringBootTest(classes = {Application.class}, webEnvironment = SpringBootTest.WebEnvironment.NONE) public class RedisOpTest { /** 注入 RedisConnection (RedisConfig 中配置)*/ @Autowired @Qualifier("RedisConnection") private RedisConnection connection; /** 注入 RedisTemplate (RedisConfig 中配置), 自定义了 key 和 value 的序列化器 */ @Autowired @Qualifier("RedisTemplate") private RedisTemplate redisTemplate; /** 注入 StringRedisTemplate, 使用默认配置 */ @Autowired private StringRedisTemplate stringRedisTemplate; @Test public void testUseRedisConnection() { String key = "RedisConnection"; // -----------------------------------使用 RedisConnection 存取 String 对象--------------------------------------- String value = "qinyi"; connection.set(key.getBytes(StandardCharsets.UTF_8), value.getBytes(StandardCharsets.UTF_8)); byte[] ret = connection.get(key.getBytes(StandardCharsets.UTF_8)); assert ret != null; System.out.println(new String(ret)); connection.flushAll(); // 慎用 // -----------------------------------使用 RedisConnection 存取 Java 对象----------------------------------------- CityInfo cityInfo = CityInfo.builder() .city("suzhou").longitude(116.58).latitude(33.38).build(); JdkSerializationRedisSerializer serializer = new JdkSerializationRedisSerializer(); connection.set(key.getBytes(StandardCharsets.UTF_8), serializer.serialize(cityInfo)); System.out.println(serializer.deserialize(connection.get(key.getBytes(StandardCharsets.UTF_8)))); connection.flushAll(); // 慎用 } @Test public void testUseRedisTemplate() { String key = "RedisTemplate"; // -----------------------------------使用 RedisTemplate 存取 Java 对象------------------------------------------- CityInfo cityInfo = CityInfo.builder() .city("suzhou").longitude(116.58).latitude(33.38).build(); ValueOperations valueOperations = redisTemplate.opsForValue(); valueOperations.set(key, cityInfo); System.out.println(valueOperations.get(key)); connection.flushAll(); // 慎用 } @Test public void testUseStringRedisTemplate() { String key = "StringRedisTemplate"; // -----------------------------------使用 StringRedisTemplate 存取 String 对象----------------------------------- CityInfo cityInfo = CityInfo.builder() .city("suzhou").longitude(116.58).latitude(33.38).build(); ValueOperations valueOperations = stringRedisTemplate.opsForValue(); valueOperations.set(key, JSON.toJSONString(cityInfo)); System.out.println(JSON.parseObject(valueOperations.get(key), CityInfo.class)); connection.flushAll(); // 慎用 } }

总结

  • 当需要存取的数据是字符串类型时(大多数情况下),使用 StringRedisTemplate
  • 当需要存取的数据是 Java Object 时,使用 RedisTemplate(需要定义好序列化策略)
  • 不需要使用 RedisConnection
  • 欢迎刚入门的Java小白朋友们加入Java学习之家9un:985331340

    里面提供免费的Java的学习资料(里面有企业级技术、日常练习案例等多个知识点的资料,每晚我还会在群内直播上课)

转载于:https://my.oschina.net/u/4005571/blog/3017646

你可能感兴趣的:(SpringBoot 中应该怎样使用 Redis ?)