SpringBoot2.1 Redis多数据源集成

在redis中,一个实例,默认有16个库,数据库名以序号命名0~15,可以根据业务需要的不同,把数据存储在不同序号的数据中。在实际应用中,该如何写配置文件,才能连接多个redis数据源呢,今天就来试一试。

在使用Redis之前,首先需要安装Redis数据库,没安装的可以参考SpringBoot初次集成Redis踩坑,安装+使用 一文,这里就不细说Redis的安装了。

本文基于SpringBoot2.1.4对Redis多数据源进行集成的。在集成的过程中用到了jedis client、Apache的commons-pool2、jackson-databind,以及spring-boot-starter-data-redis,在pom中需要把这些必须的架包引入;


            org.springframework.boot
            spring-boot-starter-web
        
        
            com.alibaba
            fastjson
            1.2.62
        
        
            org.springframework.boot
            spring-boot-configuration-processor
            true
        
        
            org.apache.commons
            commons-pool2
        
        
            com.fasterxml.jackson.core
            jackson-databind
        
        
            org.springframework.boot
            spring-boot-starter-data-redis
        
        
            redis.clients
            jedis
        

第二步,配置文件的配置;

import java.io.Serializable;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * redis配置类
 * @author 程就人生
 * @date 2019年12月16日
 */
@Configuration
@EnableCaching//开启注解式缓存
public class RedisMoreDatasourceConfig extends CachingConfigurerSupport {
 
    /**
     * 配置lettuce连接池(多数据源的公共参数)
     * GenericObjectPoolConfig不是线程安全的
     * @return
     */
    @SuppressWarnings("rawtypes")
    @Bean
    @ConfigurationProperties(prefix = "spring.redis.lettuce.pool")
    public GenericObjectPoolConfig redisPool() {
        return new GenericObjectPoolConfig<>();
    }

    /**
     * 配置第一个数据源的
     *
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.redis")
    public RedisStandaloneConfiguration redisConfig() {
        return new RedisStandaloneConfiguration();
    }

    /**
     * 配置第二个数据源
     *
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.redis2")
    public RedisStandaloneConfiguration redisConfig2() {
        return new RedisStandaloneConfiguration();
    }

    /**
     * 配置第一个数据源的连接工厂
     * 这里注意:需要添加@Primary 指定bean的名称,目的是为了创建两个不同名称的LettuceConnectionFactory
     *
     * @param config
     * @param redisConfig
     * @return
     */
    @SuppressWarnings("rawtypes")
    @Bean("factory")
    @Primary
    public LettuceConnectionFactory factory(GenericObjectPoolConfig config, RedisStandaloneConfiguration redisConfig) {
        LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder().poolConfig(config).build();
        return new LettuceConnectionFactory(redisConfig, clientConfiguration);
    }

    @SuppressWarnings("rawtypes")
    @Bean("factory2")
    public LettuceConnectionFactory factory2(GenericObjectPoolConfig config, RedisStandaloneConfiguration redisConfig2) {
        LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder().poolConfig(config).build();
        return new LettuceConnectionFactory(redisConfig2, clientConfiguration);
    }

    /**
     * 配置第一个数据源的RedisTemplate
     * 注意:这里指定使用名称=factory 的 RedisConnectionFactory
     * 并且标识第一个数据源是默认数据源 @Primary
     *
     * @param factory
     * @return
     */
    @Bean("redisTemplate")
    @Primary
    public RedisTemplate redisTemplate(@Qualifier("factory") RedisConnectionFactory factory) {
        
        RedisTemplate template = new RedisTemplate<>();
      
        template.setConnectionFactory(factory);
    
        //使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
          
        template.setValueSerializer(new JdkSerializationRedisSerializer());
          
        template.setHashKeySerializer(new StringRedisSerializer());
          
        template.setHashValueSerializer(new JdkSerializationRedisSerializer());
        
        //开启事务
        template.setEnableTransactionSupport(true);
          
        template.afterPropertiesSet();
        
        return template;
    }

    /**
     * 配置第一个数据源的RedisTemplate
     * 注意:这里指定使用名称=factory2 的 RedisConnectionFactory
     *
     * @param factory2
     * @return
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Bean("redisTemplate2")
    public RedisTemplate redisTemplate2(@Qualifier("factory2") RedisConnectionFactory factory2) {
        
         RedisTemplate template = new RedisTemplate();
         
         template.setConnectionFactory(factory2);
         
         Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
         
         ObjectMapper om = new ObjectMapper();
         
         om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
         
         om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
         
         jackson2JsonRedisSerializer.setObjectMapper(om);
         
         StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
         
         // key采用String的序列化方式
         template.setKeySerializer(stringRedisSerializer);
         
         // hash的key也采用String的序列化方式
         template.setHashKeySerializer(stringRedisSerializer);
         
         // value序列化方式采用jackson
         template.setValueSerializer(jackson2JsonRedisSerializer);
         
         // hash的value序列化方式采用jackson
         template.setHashValueSerializer(jackson2JsonRedisSerializer);
         
         template.afterPropertiesSet();
         
         return template;
    }
}

第三步,properties文件里也需要对应的参数;

#Redis common param
spring.redis.lettuce.pool.max-idle=100
spring.redis.lettuce.pool.min-idle=50
spring.redis.lettuce.pool.max-wait=2000

cache.default-exp=72
#data 0
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.redis.timeout=3000

#data 1
spring.redis2.database=1
spring.redis2.host=127.0.0.1
spring.redis2.port=6379
spring.redis2.password=
spring.redis2.timeout=3000

第四步,测试代码;

import com.alibaba.fastjson.JSONObject;

@RestController
public class IndexController {

    /**
     * 第一个数据源对应的template
     */
    @Autowired
    private RedisTemplate redisTemplate;
    
    /**
     * 第二个数据源对应的template
     */
    @Autowired
    @Qualifier("redisTemplate2")
    private RedisTemplate redisTemplate2;
    
    //测试
    @GetMapping("/index")
    public void index(){
        
        //数据库0,数据的存储及取出
        redisTemplate.opsForValue().set("aa", "aaaaa");     
        String aa = (String) redisTemplate.opsForValue().get("aa");     
        System.out.println(aa);
        
        //数据库1,数据的存储及取出
        JSONObject json = new JSONObject();
        json.put("aa", "bbbbbb");
        redisTemplate2.opsForHash().put("cc", "aa", json);  
        json = (JSONObject) redisTemplate2.opsForHash().get("cc", "aa");    
        System.out.println(json.toJSONString());
    }
}

最后,测试;启动入口程序,在浏览器上输出Controller的地址,从控制台可以看到测试的结果;

SpringBoot2.1 Redis多数据源集成_第1张图片

为了保险起见,还是去客户端查看一下存储的结果吧。


SpringBoot2.1 Redis多数据源集成_第2张图片

在做这个demo时,遇到了一些问题及总结;

  1. 把配置文件的类名命名为RedisConfig,在项目启动时会报bean名重复,这是因为和配置文件里的bean名重复了,这是需要注意的地方;
  2. 在RedisStandaloneConfiguration类中,默认的host是localhost,port是6379,database默认的是0,password默认无,这些都可以通过RedisStandaloneConfiguration的源码找到,在配置文件里没有时,就会使用默认的参数;
  3. 在RedisConnectionFactory接口里,getConnection()有两种实现方式,一种是JedisConnectionFactory,一种是LettuceConnectionFactory,本文的示例中使用的是后一种,这个可以根据个人喜好进行选择;
  4. 不管有几个数据源,最好配置一个@Primary数据源;在使用RedisTemplate时,如果不用@Qualifier注解指明,则使用默认的数据源。

你可能感兴趣的:(SpringBoot2.1 Redis多数据源集成)