Spring Boot实现Redis多数据源

目录

一、 Redis数据源配置

二、创建RedisConnection和Template


思路:

  1. Redis数据源信息的配置
    通过配置文件配置的方式在配置文件中加入新的Redis数据源信息
  2. ConnectionFactory和RedisTemplate配置
    通过BeanFactoryAware向IOC容器中注册,以达到只需要在配置文件配置连接信息就可以动态创建对应的Redis连接的目的

一、 Redis数据源配置

  1. 创建Redis配置类
    @Configuration
    @ConfigurationProperties(prefix = RedisDataSourceProperties.PREFIX)
    public class RedisDataSourceProperties {
    
        public static final String PREFIX = "spring.redis";
    
        private Map<String, RedisMessageProperties> dataSource;
    
        public Map<String, RedisMessageProperties> getDataSource() {
            return dataSource;
        }
    
        public void setDataSource(Map<String, RedisMessageProperties> dataSource) {
            this.dataSource = dataSource;
        }
    
    }
  2. 创建和RedisProperties一样的RedisMessageProperties类
  3. 此时在配置文件中配置Redis多数据源的配置示例如下
    spring:
      #默认的redis配置
      redis:
        port: 6379
        host: 127.0.0.1
        password: 123456
        database: 2
        timeout: 20000ms
        lettuce:
          pool:
            # 最大活跃链接数 默认8
            max-active: 3
            # 最大空闲连接数 默认8
            max-idle: 3
            # 最小空闲连接数 默认0
            min-idle: 0
        client-type: lettuce
      # 多数据源配置
      data-source:
        # redis1将作为 StringRedisTemplate、RedisCacheUtils和RedisBaseService的名称前缀
        redis1:
          port: 6379
          host: 127.0.0.1
          password: 123456
          database: 3
          timeout: 20000ms
          lettuce:
            pool:
              # 最大活跃链接数 默认8
              max-active: 3
              # 最大空闲连接数 默认8
              max-idle: 3
              # 最小空闲连接数 默认0
              min-idle: 0
        # redis2将作为 StringRedisTemplate、RedisCacheUtils和RedisBaseService的名称前缀
        redis2:
          port: 6379
          host: 127.0.0.1
          password: 123456
          database: 4
          timeout: 20000ms
          lettuce:
            pool:
              # 最大活跃链接数 默认8
              max-active: 3
              # 最大空闲连接数 默认8
              max-idle: 3
              # 最小空闲连接数 默认0
              min-idle: 0

二、创建RedisConnection和Template

  1. 向IOC容器中注册Bean(实现InstantiationAwareBeanPostProcessor接口很关键)
    RedisCacheUtils和RedisBaseService是自定义的Redis工具类
    @Component
    public class RedisRegister implements BeanFactoryAware, InstantiationAwareBeanPostProcessor {
    
        @Autowired
        private RedisDataSourceProperties redisDataSourceProperties;
    
        /**
         * StringRedisTemplate的beanName后缀
         */
        public static final String TEMPLATE_NAME = "StringRedisTemplate";
    
        /**
         * RedisCacheUtils的beanName后缀
         */
        public static final String UTIL_NAME = "RedisCacheUtils";
    
        /**
         * RedisBaseService的beanName后缀
         */
        public static final String SERVICE_NAME = "RedisBaseService";
    
        /**
         * 读取redis配置并创建对应的StringRedisTemplate
         *
         * @param beanFactory
         * @throws BeansException
         */
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            DefaultListableBeanFactory listableBeanFactory = (DefaultListableBeanFactory) beanFactory;
            Map<String, RedisMessageProperties> redisDataSource = redisDataSourceProperties.getDataSource();
            if (CollectionUtils.nonEmpty(redisDataSource)) {
                redisDataSource.forEach((name, dataSource) -> {
                    StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
                    RedisConnectionFactory redisConnection = getRedisConnection(dataSource);
                    stringRedisTemplate.setConnectionFactory(redisConnection);
                    stringRedisTemplate.afterPropertiesSet();
                    // 向ioc容器中注入StringRedisTemplate
                    String templateName = name + TEMPLATE_NAME;
                    listableBeanFactory.registerSingleton(templateName, stringRedisTemplate);
                    // 向ioc容器中注入RedisCacheUtils
                    RedisCacheUtils redisCacheUtils = new RedisCacheUtils(stringRedisTemplate);
                    String utilName = name + UTIL_NAME;
                    listableBeanFactory.registerSingleton(utilName, redisCacheUtils);
                    // 向ioc容器中注入RedisBaseService
                    RedisBaseService redisBaseService = new RedisBaseService(redisCacheUtils);
                    String serviceName = name + SERVICE_NAME;
                    listableBeanFactory.registerSingleton(serviceName, redisBaseService);
                });
            }
        }
    
        /**
         * 配置redisConnection
         *
         * @param dataSource
         */
        private RedisConnectionFactory getRedisConnection(RedisMessageProperties dataSource) {
            return getLettuceConnectionFactory(dataSource);
        }
    
        /**
         * 获取LettuceConnection
         *
         * @param dataSource
         */
        private RedisConnectionFactory getLettuceConnectionFactory(RedisMessageProperties dataSource) {
            RedisStandaloneConfiguration redisConfig = getRedisConfig(dataSource);
            RedisMessageProperties.Pool pool = dataSource.getLettuce().getPool();
            GenericObjectPoolConfig poolConfig = getPoolConfig(pool);
            LettucePoolingClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder()
                    .poolConfig(poolConfig).build();
            LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(redisConfig, clientConfiguration);
            connectionFactory.afterPropertiesSet();
            return connectionFactory;
        }
    
        /**
         * 获取连接池配置
         *
         * @param pool
         */
        private GenericObjectPoolConfig getPoolConfig(RedisMessageProperties.Pool pool) {
            GenericObjectPoolConfig<?> poolConfig = new GenericObjectPoolConfig<>();
            poolConfig.setMaxTotal(pool.getMaxActive());
            poolConfig.setMaxIdle(pool.getMaxIdle());
            poolConfig.setMinIdle(pool.getMinIdle());
            if (pool.getTimeBetweenEvictionRuns() != null) {
                poolConfig.setTimeBetweenEvictionRunsMillis(pool.getTimeBetweenEvictionRuns().toMillis());
            }
            if (pool.getMaxWait() != null) {
                poolConfig.setMaxWaitMillis(pool.getMaxWait().toMillis());
            }
            return poolConfig;
        }
    
        /**
         * 获取redis连接配置
         *
         * @param dataSource
         */
        private RedisStandaloneConfiguration getRedisConfig(RedisMessageProperties dataSource) {
            RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
            redisConfig.setHostName(dataSource.getHost());
            redisConfig.setPort(dataSource.getPort());
            redisConfig.setUsername(dataSource.getUsername());
            redisConfig.setPassword(RedisPassword.of(dataSource.getPassword()));
            redisConfig.setDatabase(dataSource.getDatabase());
            return redisConfig;
        }
    
    }
  2. 在项目中使用多个Redis数据源
    @Service
    public class RedisService {
    
        /**
         * 默认配置的 StringRedisTemplate
         */
        @Autowired
        private StringRedisTemplate stringRedisTemplate;
    
        /**
         * 使用redis1配置的 StringRedisTemplate
         */
        @Autowired
        @Qualifier("redis1StringRedisTemplate")
        private StringRedisTemplate redis1StringRedisTemplate;
    
        /**
         * 使用redis2配置的 StringRedisTemplate
         */
        @Autowired
        @Qualifier("redis2StringRedisTemplate")
        private StringRedisTemplate redis2StringRedisTemplate;
    
        /**
         * 默认配置的 RedisCacheUtils
         */
        @Autowired
        private RedisCacheUtils redisCacheUtils;
    
        /**
         * 使用redis1配置的 StringRedisTemplate
         */
        @Autowired
        @Qualifier("redis1RedisCacheUtils")
        private RedisCacheUtils redis1RedisCacheUtils;
    
        /**
         * 使用redis2配置的 StringRedisTemplate
         */
        @Autowired
        @Qualifier("redis2RedisCacheUtils")
        private RedisCacheUtils redis2RedisCacheUtils;
    
        /**
         * 默认配置的 RedisBaseService
         */
        @Autowired
        private RedisBaseService redisBaseService;
    
        /**
         * 使用redis1配置的 RedisBaseService
         */
        @Autowired
        @Qualifier("redis1RedisBaseService")
        private RedisBaseService redis1RedisBaseService;
    
        /**
         * 使用redis2配置的 RedisBaseService
         */
        @Autowired
        @Qualifier("redis2RedisBaseService")
        private RedisBaseService redis2RedisBaseService;
    
    }

    在 RedisRegister 中需要实现 InstantiationAwareBeanPostProcessor,在IOC容器加载所有bean之前会扫描所有实现了 InstantiationAwareBeanPostProcessor 接口的类

    因为RedisRegister需要保证 setBeanFactory(BeanFactory beanFactory) 优先加载,不然在 RedisService中引用的自定义bean会抛NPE


版权声明:本文为qq_41548206原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。