zoukankan      html  css  js  c++  java
  • spring boot整合redis多实例

    最近项目中遇到需要连接两个redis实例的情况,于是就在spring boot原先的基础上修改了一点。

    首先,添加所需的依赖

            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-pool2</artifactId>
                <version>2.7.0</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
    

    1. 定义配置文件的bean,继承自RedisProperties

    • 下面是配置文件的内容
    redis:
      config:
        multiple:
        - name: develop
          database: 0
          lettuce:
            pool:
              max-idle: 10
              max-active: 1000
              max-wait: 1000ms
              min-idle: 5
          timeout: 100000ms
          cluster:
            nodes: 192.168.2.86:6380,192.168.2.87:6380,192.168.2.88:6380
        - name: test
          database: 0
          lettuce:
            pool:
              max-idle: 10
              max-active: 1000
              max-wait: 1000ms
              min-idle: 5
          timeout: 100000ms
          cluster:
            nodes: 192.168.2.86:6379,192.168.2.87:6379,192.168.2.88:6379
    
    • 配置文件对应的实体
    @Data
    public class MultipleRedisProperties extends RedisProperties {
    
        /**
         * redis的自定义名称
         */
        private String name;
    
    }
    

    2. 获取配置文件属性的值

    @Getter
    @Setter
    @ConfigurationProperties(prefix = "redis.config")
    public class RedisConfigPropertySupport {
    
    
        List<MultipleRedisProperties> multiple = new ArrayList<>();
    
    
    }
    

    3.加载到spring 容器中

    @Getter
    @Setter
    @Configuration
    @EnableConfigurationProperties(RedisConfigPropertySupport.class)
    public class RedisPropertiesAutoConfig {
    
        private RedisConfigPropertySupport redisProperties;
    
        public RedisPropertiesAutoConfig(RedisConfigPropertySupport redisProperties) {
            this.redisProperties = redisProperties;
        }
    }
    
    • 创建redis部署模式的枚举值
    public enum RedisModeEnum {
    
        /**
         * 单机
         */
        STAND_ALONE,
    
        /**
         * 哨兵
         */
        SENTINEL,
    
        /**
         * 集群
         */
        CLUSTER
    
    }
    

    4. 使用spring boot的创建连接工厂进行配置redis的连接工厂类

    public abstract class AbstractRedisConnectionFactoryConfig implements BeanFactoryAware, InitializingBean {
    
        @Autowired
        private RedisPropertiesAutoConfig redisProperties;
    
        private BeanFactory beanFactory;
    
        private static final String DEFAULT = "default";
    
    
        @Override
        public void afterPropertiesSet() {
            ConfigurableListableBeanFactory listableBeanFactory = (ConfigurableListableBeanFactory) this.getBeanFactory();
            if (getRedisProperties().getRedisProperties() == null || CollectionUtils.isEmpty(getRedisProperties().getRedisProperties().getMultiple())) {
                RedisConnectionFactory defaultConnectionFactory = buildRedisConnectionFactory(null);
                listableBeanFactory.registerSingleton(DEFAULT + "_redisConnectionFactory", defaultConnectionFactory);
            }
            getRedisProperties().getRedisProperties().getMultiple().forEach(redisProperty -> {
                RedisConnectionFactory redisConnectionFactory = buildRedisConnectionFactory(redisProperty);
                listableBeanFactory.registerSingleton(redisProperty.getName().trim() + "_redisConnectionFactory", redisConnectionFactory);
            });
        }
    
        /**
         * 创建{@link RedisConnectionFactory},由子类实现
         *
         * @param redisProperties
         * @return
         */
        protected abstract RedisConnectionFactory buildRedisConnectionFactory(RedisProperties redisProperties);
    
        /**
         * 根据redisProperty判断redis部署模式
         *
         * @param redisProperty redisProperty
         * @return {@link RedisModeEnum}
         */
        protected abstract RedisModeEnum getRedisMode(RedisProperties redisProperty);
    
    
        static class RedisConnectionPoolBuilderFactory {
    
            public LettuceClientConfiguration.LettuceClientConfigurationBuilder createBuilder(RedisProperties.Pool properties) {
                return LettucePoolingClientConfiguration.builder().poolConfig(getPoolConfig(properties));
            }
    
            private GenericObjectPoolConfig<?> getPoolConfig(RedisProperties.Pool properties) {
                GenericObjectPoolConfig<?> config = new GenericObjectPoolConfig<>();
                config.setMaxTotal(properties.getMaxActive());
                config.setMaxIdle(properties.getMaxIdle());
                config.setMinIdle(properties.getMinIdle());
                if (properties.getTimeBetweenEvictionRuns() != null) {
                    config.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRuns().toMillis());
                }
                if (properties.getMaxWait() != null) {
                    config.setMaxWaitMillis(properties.getMaxWait().toMillis());
                }
                return config;
            }
        }
    
    
        @Override
        public void setBeanFactory(@Nullable BeanFactory beanFactory) throws BeansException {
            this.beanFactory = beanFactory;
        }
    
        public BeanFactory getBeanFactory() {
            return beanFactory;
        }
    
        public RedisPropertiesAutoConfig getRedisProperties() {
            return redisProperties;
        }
    }
    
    • 工厂实现类
    @Configuration
    public class LettuceRedisConnectionFactoryConfig extends AbstractRedisConnectionFactoryConfig {
    
    
        @Override
        protected RedisConnectionFactory buildRedisConnectionFactory(RedisProperties redisProperty) {
            if (redisProperty == null) {
                //创建默认的redis连接工厂
                LettuceConnectionFactory defaultConnectionFactory = createDefaultConnectionFactory();
                
                defaultConnectionFactory.afterPropertiesSet();
                return defaultConnectionFactory;
            }
            LettuceClientConfiguration clientConfig = buildLettuceClientConfiguration(DefaultClientResources.create(),
                    redisProperty.getLettuce().getPool(), redisProperty);
            //创建lettuce连接工厂
            LettuceConnectionFactory redisConnectionFactory;
            if (getRedisMode(redisProperty) == RedisModeEnum.CLUSTER) {
                redisConnectionFactory = new LettuceConnectionFactory(new RedisClusterConfiguration
                        (redisProperty.getCluster().getNodes()), clientConfig);
            } else if (getRedisMode(redisProperty) == RedisModeEnum.SENTINEL) {
                redisConnectionFactory = new LettuceConnectionFactory(new RedisSentinelConfiguration
                        (redisProperty.getSentinel().getMaster(), new HashSet<>(redisProperty.getSentinel().getNodes())), clientConfig);
            } else {
                redisConnectionFactory = new LettuceConnectionFactory(new RedisStandaloneConfiguration
                        (redisProperty.getHost(), redisProperty.getPort()), clientConfig);
            }
           
            redisConnectionFactory.afterPropertiesSet();
            return redisConnectionFactory;
        }
    
        @Override
        protected RedisModeEnum getRedisMode(RedisProperties redisProperty) {
            if (redisProperty.getCluster() != null) {
                Assert.notNull(redisProperty.getCluster().getNodes(), "集群节点不能为空");
                return RedisModeEnum.CLUSTER;
            } else if (redisProperty.getSentinel() != null) {
                Assert.hasText(redisProperty.getSentinel().getMaster(), "哨兵的主节点不能为空");
                Assert.notNull(redisProperty.getSentinel().getNodes(), "哨兵的从节点不能为空");
                return RedisModeEnum.SENTINEL;
            }
            return RedisModeEnum.STAND_ALONE;
        }
    
        private LettuceClientConfiguration buildLettuceClientConfiguration(ClientResources clientResources, RedisProperties.Pool pool, RedisProperties redisProperties) {
            LettuceClientConfiguration.LettuceClientConfigurationBuilder builder = createBuilder(pool);
            applyProperties(builder, redisProperties);
            builder.clientResources(clientResources);
            return builder.build();
        }
    
        private LettuceClientConfiguration.LettuceClientConfigurationBuilder applyProperties(
                LettuceClientConfiguration.LettuceClientConfigurationBuilder builder, RedisProperties redisProperties) {
            if (redisProperties.isSsl()) {
                builder.useSsl();
            }
            if (redisProperties.getTimeout() != null) {
                builder.commandTimeout(redisProperties.getTimeout());
            }
            if (redisProperties.getLettuce() != null) {
                RedisProperties.Lettuce lettuce = redisProperties.getLettuce();
                if (lettuce.getShutdownTimeout() != null && !lettuce.getShutdownTimeout().isZero()) {
                    builder.shutdownTimeout(redisProperties.getLettuce().getShutdownTimeout());
                }
            }
            return builder;
        }
    
        private LettuceClientConfiguration.LettuceClientConfigurationBuilder createBuilder(RedisProperties.Pool pool) {
            if (pool == null) {
                return LettuceClientConfiguration.builder();
            }
            return new RedisConnectionPoolBuilderFactory().createBuilder(pool);
        }
    
        private LettuceConnectionFactory createDefaultConnectionFactory() {
            return new LettuceConnectionFactory(new RedisStandaloneConfiguration());
        }
    }
    

    5.redisTemplate的配置

    public abstract class AbstractRedisConfiguration implements ApplicationContextAware {
    
        private ApplicationContext applicationContext;
    
        protected RedisTemplate<String, Object> buildRedisTemplate(String name) {
            return buildRedisTemplate(name, new GenericJackson2JsonRedisSerializer(), false);
        }
    
        protected RedisTemplate<String, Object> buildRedisTemplate(String name, Boolean enableTransaction) {
            return buildRedisTemplate(name, new GenericJackson2JsonRedisSerializer(), enableTransaction);
        }
    
        protected RedisTemplate<String, Object> buildRedisTemplate(String name, RedisSerializer redisSerializer,
                                                                   Boolean enableTransaction) {
            if (StringUtils.isBlank(name)) {
                throw new IllegalArgumentException("redis properties name field must not null");
            }
            RedisConnectionFactory redisConnectionFactory = getRedisConnectionFactory(name);
            RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
            redisTemplate.setConnectionFactory(redisConnectionFactory);
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setHashKeySerializer(new StringRedisSerializer());
            redisTemplate.setValueSerializer(redisSerializer);
            redisTemplate.setHashValueSerializer(redisSerializer);
            redisTemplate.setEnableTransactionSupport(enableTransaction);
            return redisTemplate;
        }
    
    
        private RedisConnectionFactory getRedisConnectionFactory(String name) {
            return (RedisConnectionFactory) applicationContext.getBean(name.trim() + "_redisConnectionFactory");
        }
    
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.applicationContext = applicationContext;
        }
    
    }
    
    • 配置redisTemplate
    @Configuration
    @DependsOn("lettuceRedisConnectionFactoryConfig")
    public class RedisConfiguration extends AbstractRedisConfiguration {
    
    
        @Bean("developRedisTemplate")
        public RedisTemplate<String, Object> getDevelopRedisTemplate() {
            return buildRedisTemplate("develop");
        }
    
        @Bean("testRedisTemplate")
        public RedisTemplate<String, Object> getTestRedisTemplate() {
            return buildRedisTemplate("test");
        }
    }
    
    • 下面利用spring boot的ApplicationRunner接口测试一下,用redis客户端查看发现结果已经存入进去了。
         @Autowired
        @Qualifier("developRedisTemplate")
        private RedisTemplate developRedisTemplate;
    
        @Autowired
        @Qualifier("testRedisTemplate")
        private RedisTemplate testRedisTemplate;
    
    
       @Override
        public void run(ApplicationArguments args) throws Exception {
            developRedisTemplate.opsForValue().set("develop_RedisMultiple", "test", 120, TimeUnit.SECONDS);
            testRedisTemplate.opsForValue().set("test_RedisMultiple", "test", 120, TimeUnit.SECONDS);
        }
    
  • 相关阅读:
    volatile 能使得一个非原子操作变成原子操作吗?
    什么是线程局部变量?
    使用idea插件进行java代码生成
    mybatis plus+dynamic事务导致多数据源切换失败
    10_docker-compose
    Ubuntu的Python从2.x升级到3.x
    idea查看控制台数据mybatis的sql完整语句
    iframe高度处理
    angular路由
    去掉iPhone、iPad的默认按钮、输入框样式
  • 原文地址:https://www.cnblogs.com/wenwblog/p/11784166.html
Copyright © 2011-2022 走看看