Redis - ⭐Spring Data Redis 配置

894 阅读5分钟

概述

  1. 定义

    1. SpringData:Spring 中数据操作的模块,包含各种数据库的集成

    2. SpringDataRedis:SpringData 对 Redis 的集成模块,整合了 Jedis 和 lettuce 的一套 API 接口

    3. RedisTemplate:Spring Boot 访问 Redis 的核心组件,底层通过 RedisConnectionFactory 对多种 Redis 驱动进行集成,默认采用的是JDK的序列化策略

    • StringRedisTemplate:RedisTemplate的子类,默认采用的是 String 的序列化策略,保存的 key 和 value 都是采用此策略序列化保存的。
  2. 功能

    1. 提供不同 Redis 客户端的整合、提供统一 API 操作 Redis
    2. 支持 Redis 发布订阅模型、哨兵、集群
    3. 支持基于 lettuce 的响应式编程
    4. 支持基于 JDK / JSON / String / Spring 对象的数据序列化和反序列化
    5. 支持基于 Redis 的 JDK Collection 实现

QuickStart

    1. 引入依赖
        <dependencies>
            <!--redis依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <!--common-pool-->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-pool2</artifactId>
            </dependency>
            <!--Jackson依赖-->
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
    1. 配置文件
    spring:
      redis:
        host: 192.168.150.101
        port: 6379
        password: 123321
        lettuce:
          pool:
            max-active: 8
            max-idle: 8
            min-idle: 0
            max-wait: 100ms
    
    1. 依赖注入 & 测试
    @SpringBootTest
    class RedisStringTests {
    
        @Autowired
        private RedisTemplate redisTemplate;
    
        @Test
        void testString() {
            // 写入一条String数据
            redisTemplate.opsForValue().set("name", "alec");
            // 获取string数据
            Object name = stringRedisTemplate.opsForValue().get("name");
            System.out.println("name = " + name);
        }
    }
    

配置文件

  1. application.yaml

    spring:
      redis:
        host: 192.168.150.101   # Redis服务所在IP
        port: 6379              # Redis服务所在端口
        password: 123321        # Redis服务连接密码
        lettuce:                # 声明连接工厂的参数, 在@Configuration配置中自动作为connectionFactory形参
          pool:
            max-active: 8
            max-idle: 8
            min-idle: 1
            max-wait: 100ms
    

RedisTemplate 工具类

  1. 定义:封装对 Redis 各种数据类型的操作到不同的类中

  2. 使用方法:通常做法是自定义 RedisTemplate 的 Bean 实例,自定义具体的序列化策略

  3. 数据结构操作分类(详情:数据类型 & 常用命令

    操作方式操作对象结构的读写能力
    redisTemplate.opsForValue()String对整个字符串或字符串的一部分进行操作;
    对整数或浮点数进行自增或自减操作;
    redisTemplate.opsForHash()Hash添加、获取、删除单个元素
    redisTemplate.opsForList()List对链表的两端进行push和pop操作;
    读取单个或多个元素;根据值查找或删除元素;
    redisTemplate.opsForSet()Set是否存在、添加、获取、删除;
    计算交集、并集、差集;
    redisTemplate.opsForZSet()Set有添加、获取、删除单个元素;
    根据分值范围或成员来获取元素;
  4. 常用方法

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

    1. RedisTemplate:要实例化的 Bean 对象

    2. RedisConnectionFactory:Redis 连接的抽象工厂,决定了 RedisTemplate 如何与 Redis 服务器进行交互

    3. ObjectMapper: Jackson 库中的核心类,用于自定义序列化行为

      1. Accessor.ALL:设置序列化属性访问器,会通过一切属性访问器去访问public属性
      2. Visibility.ANY:设置序列化可见性,让访问器能够访问任何访问权限(public/protected/private)的方法
      3. DefaultTyping.NON_FINAL:设置对非 final 类型序列化时, 将类信息也存储在序列化的json字符串中('@class'属性)作为一个属性(property)
    4. KeySerializer/HashKeySerializer:手动设置 Key 和 HashKey 的序列化方式

    5. ValueSerializer/HashValueSerializer:手动设置 Value 和 HashValue 的序列化方式

    @Configuration
    @EnableConfigurationProperties({RedisProperties.class})
    public class RedisConfig {
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
    				// 自定义序列化行为
            ObjectMapper om = new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
            Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = new Jackson2JsonRedisSerializer<>(om, Object.class);
     
            // 创建RedisTemplate对象
            RedisTemplate<String, Object> template = new RedisTemplate<>();
            // 设置连接工厂
            template.setConnectionFactory(connectionFactory);
            // 设置Key的序列化方式为String(StringRedisSerializer)
            template.setKeySerializer(RedisSerializer.string());
            template.setHashKeySerializer(RedisSerializer.string());
    				// 设置Value的序列化方式为Json(Jackson2JsonRedisSerializer)
            template.setValueSerializer(jsonRedisSerializer);
            template.setHashValueSerializer(jsonRedisSerializer);
            template.afterPropertiesSet();
            return template;
        }
    }
    

StringRedisTemplate

  1. 定义:”RedisTemplate” 的子类,区别是 StringRedisTemplate 的 key-value 都只能是 String 类型的

  2. **优点:**存入 Redis 的数据中没有标记数据类的属性,更加节省空间

  3. **缺点:**key-value 都只能是 String 类型的,对于 “Object 对象” 需要手动序列化和反序列化,数据和对象的绑定需要程序员使用代码逻辑解决

  4. 类定义

    public class StringRedisTemplate extends RedisTemplate<String, String> {
        public StringRedisTemplate() {
            this.setKeySerializer(RedisSerializer.string());
            this.setValueSerializer(RedisSerializer.string());
            this.setHashKeySerializer(RedisSerializer.string());
            this.setHashValueSerializer(RedisSerializer.string());
        }
    
        public StringRedisTemplate(RedisConnectionFactory connectionFactory) {
            this();
            this.setConnectionFactory(connectionFactory);
            this.afterPropertiesSet();
        }
    
        protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {
            return new DefaultStringRedisConnection(connection);
        }
    }
    
  5. ⭐ 常用方法

    返回值类型方法value 类型功能
    voidopsForValue().set("key", "value")String添加 key-value 键值对
    StringopsForValue().get("key")String获取 key 对应的 value 值
    voidopsForHash().put("hashKey", "field", "value")HashMap<field, value>添加 key - HashSet<field, value> 的 field 字段
    StringopsForHash().get("hashKey", "field")HashMap<field, value>获取 key - HashSet<field, value> 的 field 字段
    LongopsForList().leftPush("listKey", "value")List添加 key - List 的 List 元素,返回添加后 list 的长度
    StringopsForList().leftPop("listKey")List获取 key - List 的 List 元素
    LongopsForSet().add("setKey", "value")HashSet添加 key - Set 的 set 元素,返回添加后 set 的大小
    SetopsForSet().members("setKey")HashSet获取 key - Set 的 set 元素

⭐ 示例

    1. 引入依赖
    <dependencies>
        <!--redis依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--common-pool-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <!--Jackson依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
    1. ⭐配置 Redis 服务器(/src/main/resources/application.yaml)
    spring:
      redis:
        host: 192.168.150.101   # Redis服务所在IP
        port: 6379              # Redis服务所在端口
        password: 123321        # Redis服务连接密码
        lettuce:                # 声明连接工厂的参数, 在@Configuration配置中自动作为connectionFactory形参
          pool:
            max-active: 8
            max-idle: 8
            min-idle: 1
            max-wait: 100ms
    
    1. 自定义序列化方式 (修改 Spring 配置中的 RedisTemplate 类)
    2. RedisTemplate:要实例化的 Bean 对象
    3. RedisConnectionFactory:Redis 连接的抽象工厂,决定了 RedisTemplate 如何与 Redis 服务器进行交互
    4. KeySerializer/HashKeySerializer:手动设置 Key 和 HashKey 的序列化方式
    5. ValueSerializer/HashValueSerializer:手动设置 Value 和 HashValue 的序列化方式
    @Configuration
    public class RedisConfig {
    
    		// 创建一个接受<String, Object>类型的RedisTemplate对象, 添加到Configuration的Bean中,实现依赖注入
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){
            // 创建RedisTemplate对象
            RedisTemplate<String, Object> template = new RedisTemplate<>();
            // 设置连接工厂
            template.setConnectionFactory(connectionFactory);
            // 设置Key的序列化方式为String(StringRedisSerializer)
            template.setKeySerializer(RedisSerializer.string());
            template.setHashKeySerializer(RedisSerializer.string());
            // 设置Value的序列化格式为JSON (先要创建一个JSON序列化工具)
            GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
            template.setValueSerializer(jsonRedisSerializer);
            template.setHashValueSerializer(jsonRedisSerializer);
            // 将设置好的RedisTemplate作为Bean对象交给IOC容器
            return template;
        }
    }
    
    1. ⭐使用 StringRedisTemplate (需要手动序列化和反序列化)
    @SpringBootTest
    class RedisStringTests {
    
        @Autowired
        private StringRedisTemplate stringRedisTemplate;
    
        @Test
        void testString() {
            stringRedisTemplate.opsForValue().set("verify:phone:13600527634", "124143");        // 写入一条String数据
            Object name = stringRedisTemplate.opsForValue().get("name");                        // 获取string数据
            System.out.println("name = " + name);
        }
    
        private static final ObjectMapper mapper = new ObjectMapper();
    
        @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("user1 = " + user1);
        }
    
    }