---
url: /diary/as2oixqx/index.md
description: 封装 Redis 缓存操作的 Spring Boot Starter，提供统一的缓存管理接口和便捷的注解支持。
---
## 前言

`springcloud`项目通常会遇到以下2个问题：

1. **配置项目**`redis`组件时，有时会遇到一些序列化的问题，如当使用`jackson`的时，使用`@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)`注解，会报这个实体不是一个数组的问题
2. **集成通用**`redis`依赖组件，可以让所有的项目共同依赖
3. **默认一个**`redis`过期时间，更好的利用`redis`资源

## 正文

### 项目依赖

`Springboot` : 2.6.3

`Springcloud`: 2021.0.1

`Springcoud Alibaba`: 2021.0.1.0

`redis`依赖

```xml :collapsed-lines
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
    <parent>
        <artifactId>framework-common</artifactId>
        <groupId>com.xxx</groupId>
        <version>2.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>framework-common-redis</artifactId> 

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

</project>
```

### 配置redis序列

```java :collapsed-lines
@Configuration
@AutoConfigureBefore(RedisAutoConfiguration.class)
public class BaseRedisConfig {

    @Bean
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        redisTemplate.setKeySerializer(RedisSerializer.string());
        redisTemplate.setHashKeySerializer(RedisSerializer.string());
        redisTemplate.setValueSerializer(RedisSerializer.json());
        redisTemplate.setHashValueSerializer(RedisSerializer.json());
        return redisTemplate;
    }

}

/**
 * redis 默认缓存时间
 */
@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
//设置Redis缓存有效期为7天
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
      // 使的reids注解缓存的key中 "::"2个冒号转换成":"一个冒号，统一redis key的风格
.computePrefixWith(name -> name + ":")
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())).entryTtl(Duration.ofDays(7));
return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
}
}
```

#### 代码解释

`@AutoConfigureBefore`注解是`Spring Boot`的一个注解，用于指定一个配置类在另外一个配置类之前自动配置，以确保它们的顺序正确。它的作用是控制自动配置的顺序，以便在自动配置时确定配置类的优先级。

**使用**`@AutoConfigureBefore`注解需要在配置类上加上该注解，并指定目标配置类的全限定名或Class对象。

**例如，我们可以在自定义的Redis配置类上使用**`@AutoConfigureBefore`注解，指定目标为框架提供的默认Redis配置类，使自定义Redis配置类在框架默认Redis配置类之前进行自动配置。

**示例代码如下所示：**

```java
@Configuration
@AutoConfigureBefore(RedisAutoConfiguration.class)
public class CustomRedisConfiguration {
   // 自定义 Redis 配置
}
```

**在上述代码中，我们在配置类**`CustomRedisConfiguration`上使用`@AutoConfigureBefore`注解，指定目标为`Spring Boot`框架提供的默认`Redis`配置类`RedisAutoConfiguration`，以确保自定义的`Redis`配置类在框架默认`Redis`配置类之前自动配置。

**总而言之，**`@AutoConfigureBefore`注解可以帮助我们控制自动配置的顺序，确保在自动配置时配置类的优先级正确。

`RedisSerializer.string()`实际为`StringRedisSerializer.UTF_8`，获取一个简单的 String byte\[]（和返回）序列化程序，使用 UTF-8 作为默认值，简单来讲，就是`key`必须是`String`类型，这个在使用`BoundXXXOperations`方法时，若`key`不为`String`类型，则会抛出错误。

```java
redisTemplate.setValueSerializer(RedisSerializer.json());
redisTemplate.setHashValueSerializer(RedisSerializer.json());
```

**以上两句代码指将普通数据类型的**`value`和哈希结构的`value`值使用`json`序列化，看下具体内容：

```java
static RedisSerializer<Object> json() {
return new GenericJackson2JsonRedisSerializer();
}
```

**实际上是通过了**`jackson`来进行序列化和逆序列化。使用json序列化的好处是可以使用`@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)`来序列化bean，这个注解在入库或者缓存后，会加上`@class`，使得逆序列化更为准确，且可实现多态逆序列化。

`computePrefixWith(name -> name + ":")`可以让使得`springboot-data-reids`注解缓存的key中的`::`两个冒号转换成`:`一个冒号，统一`redis` key的风格，更好的管理`redis`键值。

```
xxx::date::1234
转变成了
xxx:data:1234
```

### 添加spring.factories

`spring.factories` 是 Spring 框架中的一个特殊文件，在 `Spring Boot` 中被广泛使用。它的作用是使开发者可以为自己的应用程序添加自定义配置，例如注册自定义的 `Bean` 或者自定义的 `Starter`。

**具体地说，**`spring.factories` 文件中包含了多个键值对，其中键是某个接口或者类的全限定名，而值是对应该接口或类实现的工厂类的全限定名。当 Spring Boot 启动时，会扫描项目中的所有 `spring.factories` 文件，并读取其中的配置信息，最终根据这些配置信息初始化并启动`Spring` 上下文。

`Spring Boot` 中的 `Starter` 就是通过使用 `spring.factories` 实现的。我们可以构建一个 `Starter`（一个所需依赖的组合）并定义其`spring.factories` 文件来注册自定义的自动配置。这样，当使用该 `Starter` 的应用程序启动时，`Spring Boot`就会根据 `spring.factories` 中的配置信息自动装配所需的 `Bean`，为提供了开发者非常方便的方式来为自己的应用程序添加自定义配置。

**在**`resource`下新建`META-INF`目录，在`META-INF`目录下新建`spring.factories`文件，在文件里加入之前自定义的`BaseRedisConfig`.

```properties
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.xxx.common.redis.config.BaseRedisConfig
```

### 打包

`maven clean install`

### 使用

**其他项目引入依赖**`framework-common-redis`

`yml`文件配置redis：

```yaml
spring:
  redis:
    database: 0
    port: 6379
    host: localhost
    password: L1lvlrGZV6Kl0bhS
    lettuce:
      pool:
        # 连接池最大连接数
        max-active: 200
        # 连接池最大阻塞等待时间（使用负值表示没有限制）
        max-wait: -1ms
        # 连接池中的最大空闲连接
        max-idle: 10
        # 连接池中的最小空闲连接
        min-idle: 0
```

ps：若使用`Spring boot3`则`pom`文件为

```yaml
spring:
  data:
    redis:
      database: 0
      port: 6379
      host: localhost
      password: L1lvlrGZV6Kl0bhS
      lettuce:
        pool:
          # 连接池最大连接数
          max-active: 200
          # 连接池最大阻塞等待时间（使用负值表示没有限制）
          max-wait: -1ms
          # 连接池中的最大空闲连接
          max-idle: 10
          # 连接池中的最小空闲连接
          min-idle: 0
```
